<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>April is your lie</title>
  <subtitle>四月是你的谎言</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://windrunnerlihuan.com/"/>
  <updated>2019-03-27T15:01:19.431Z</updated>
  <id>http://windrunnerlihuan.com/</id>
  
  <author>
    <name>windrunnerlihuan</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Chromium学习之路(一)----智能指针实现原理分析</title>
    <link href="http://windrunnerlihuan.com/2019/03/25/Chromium%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B8%80-%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86%E5%88%86%E6%9E%90/"/>
    <id>http://windrunnerlihuan.com/2019/03/25/Chromium学习之路-一-智能指针实现原理分析/</id>
    <published>2019-03-25T09:07:11.000Z</published>
    <updated>2019-03-27T15:01:19.431Z</updated>
    
    <content type="html">&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Chromium和WebKit的智能指针实现原理分析。&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;智能指针概述&quot;&gt;&lt;a href=&quot;#智能指针概述&quot; class=&quot;headerlink&quot; title=&quot;智能指针概述&quot;&gt;&lt;/a&gt;智能指针概述&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;智能指针对于写c艹程序的开发人员来说并不陌生，尤其大一点的程序，也是司空见惯。（容我吐槽一下自己，接触webrtc中也有大量的智能指针，奈何我是个c艹新手）WebKit和Chromium都是C艹开发的，在解决对象释放问题时，要做到在对象不需要时自动释放，因为手动释放会带来忘记释放或者释放后又继续使用的隐患。智能指针是实现对象自动释放的有效技术手段。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;之前文章有一篇&lt;a href=&quot;http://windrunnerlihuan.com/2016/08/23/智能指针简单分析/&quot;&gt;智能指针简单分析&lt;/a&gt;，在Android系统源码里用到了大量的sp和wp相关的代码。sp和wp就是android系统提供的智能指针模版类，前者用来实现强引用，后者用来实现弱饮用。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;引用一段对智能指针的描述：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在广义上，智能指针划分为两类。第一类智能指针引用的对象是可以共享的，也就是一个对象可以同时被多个智能指针引用。这类智能指针要求被引用的对象具有计数的功能，数值的大小就表示它目前被多少个智能指针引用。当一个对象的引用计数值等于0的时候，就表示它要被释放了。这类智能指针适合作为函数参数或者返回值在模块之间进行传递，从而实现共享。第二类智能指针不要求被引用对象具有计数的功能。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;第二类智能指针引用的对象是独占的，也就是一个对象同一时刻只可以被一个智能指针引用。这类智能指针不要求被引用对象具有计数的功能。只要这类智能指针的生命周期超出了它自己的范围，那么它引用的对象就会被自动销毁。这类智能指针适合在函数或者内部使用，用来自动化释放那些不需要了的对象。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Chromium和WebKit还提供了弱智能指针，就是他们的存在不会影响被引用对象的生命周期。他们适合来解决对象这件存在的循环引用问题。再次饮用一段介绍：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在计算机科学领域中，提供垃圾收集（Garbage Collection）功能的系统框架，即提供对象托管功能的系统框架，例如Java应用程序框架，也是采用上述的引用计数技术方案来实现的，然而，简单的引用计数技术不能处理系统中对象间循环引用的情况。考虑这样的一个场景，系统中有两个对象A和B，在对象A的内部引用了对象B，而在对象B的内部也引用了对象A。当两个对象A和B都不再使用时，垃圾收集系统会发现无法回收这两个对象的所占据的内存的，因为系统一次只能收集一个对象，而无论系统决定要收回对象A还是要收回对象B时，都会发现这个对象被其它的对象所引用，因而就都回收不了，这样就造成了内存泄漏。这样，就要采取另外的一种引用计数技术了，即对象的引用计数同时存在强引用和弱引用两种计数，例如，Apple公司提出的Cocoa框架，当父对象要引用子对象时，就对子对象使用强引用计数技术，而当子对象要引用父对象时，就对父对象使用弱引用计数技术，而当垃圾收集系统执行对象回收工作时，只要发现对象的强引用计数为0，而不管它的弱引用计数是否为0，都可以回收这个对象，但是，如果我们只对一个对象持有弱引用计数，当我们要使用这个对象时，就不直接使用了，必须要把这个弱引用升级成为强引用时，才能使用这个对象，在转换的过程中，如果对象已经不存在，那么转换就失败了，这时候就说明这个对象已经被销毁了，不能再使用了。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;因此要分别分析WebKit和Chromium的智能指针，好在Android源码里面都有，都位于external/chromuim_org/下面，之前下过android源码就可以直接查看了。&lt;/p&gt;
&lt;h1 id=&quot;WebKit智能指针&quot;&gt;&lt;a href=&quot;#WebKit智能指针&quot; class=&quot;headerlink&quot; title=&quot;WebKit智能指针&quot;&gt;&lt;/a&gt;WebKit智能指针&lt;/h1&gt;&lt;h2 id=&quot;第一类智能指针&quot;&gt;&lt;a href=&quot;#第一类智能指针&quot; class=&quot;headerlink&quot; title=&quot;第一类智能指针&quot;&gt;&lt;/a&gt;第一类智能指针&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WebKit第一类智能指针由RefPtr实现，它的基类是RefCounted，提供引用计数功能。当一个对象可以被类RefPtr描述的对象引用时，它就必须要从基类RefCounted继承下来。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;RefCounted是一个模板类，为了减少编译时的代码膨胀，RefCounted类是从另外一个非模板类RefCountedBase继承下来的。RefCountedBase类才是负责提供计数功能的基类，位于external/chromium_org/third_party/WebKit/Source/wtf/RefCounted.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;96&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;97&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;98&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;99&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;100&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;101&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;102&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;103&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;104&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;105&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;106&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;107&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;108&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;109&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;110&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;111&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;112&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;113&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;114&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;115&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;116&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;117&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;118&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;119&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;120&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;121&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;122&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;123&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;124&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; WTF_EXPORT RefCountedBase &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; CHECK_REF_COUNTED_LIFECYCLE&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Start thread verification as soon as the ref count gets to 2. This&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// heuristic reflects the fact that items are often created on one thread&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// and then given to another thread to be used.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;FIXME:&lt;/span&gt; Make this restriction tigher. Especially as we move to more&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// common methods for sharing items across threads like CrossThreadCopier.h&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// We should be able to add a &quot;detachFromThread&quot; method to make this explicit.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (m_refCount == &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            m_verifier.setShared(&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// If this assert fires, it either indicates a thread safety issue or&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// that the verification needs to change. See ThreadRestrictionVerifier for&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// the different modes.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ASSERT(m_verifier.isSafeToUse());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ASSERT(!m_adoptionIsRequired);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ASSERT_WITH_SECURITY_IMPLICATION(!m_deletionHasBegun);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//这才是重点，饮用计数+1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ++m_refCount;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;hasOneRef&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ASSERT_WITH_SECURITY_IMPLICATION(!m_deletionHasBegun);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; CHECK_REF_COUNTED_LIFECYCLE&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ASSERT(m_verifier.isSafeToUse());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; m_refCount == &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;refCount&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; CHECK_REF_COUNTED_LIFECYCLE&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ASSERT(m_verifier.isSafeToUse());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; m_refCount;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    RefCountedBase()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        : m_refCount(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)&lt;span class=&quot;comment&quot;&gt;//默认创建时候引用计数为1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; SECURITY_ASSERT_ENABLED&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        , m_deletionHasBegun(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; CHECK_REF_COUNTED_LIFECYCLE&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        , m_adoptionIsRequired(&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ~RefCountedBase()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ASSERT_WITH_SECURITY_IMPLICATION(m_deletionHasBegun);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; CHECK_REF_COUNTED_LIFECYCLE&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ASSERT(!m_adoptionIsRequired);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Returns whether the pointer should be freed or not.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;derefBase&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ASSERT_WITH_SECURITY_IMPLICATION(!m_deletionHasBegun);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; CHECK_REF_COUNTED_LIFECYCLE&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ASSERT(m_verifier.isSafeToUse());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ASSERT(!m_adoptionIsRequired);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ASSERT(m_refCount &amp;gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//引用计数-1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        --m_refCount;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果引用计数为0，就return true，为后面的删除对象作出判断&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!m_refCount) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; SECURITY_ASSERT_ENABLED&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            m_deletionHasBegun = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; CHECK_REF_COUNTED_LIFECYCLE&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Stop thread verification when the ref goes to 1 because it&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// is safe to be passed to another thread at this point.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (m_refCount == &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            m_verifier.setShared(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; CHECK_REF_COUNTED_LIFECYCLE&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;deletionHasBegun&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; m_deletionHasBegun;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; CHECK_REF_COUNTED_LIFECYCLE || SECURITY_ASSERT_ENABLED&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;friend&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;adopted&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(RefCountedBase*)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; m_refCount;&lt;span class=&quot;comment&quot;&gt;//引用计数，核心变量&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; SECURITY_ASSERT_ENABLED&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; m_deletionHasBegun;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; CHECK_REF_COUNTED_LIFECYCLE&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; m_adoptionIsRequired;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ThreadRestrictionVerifier m_verifier;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; CHECK_REF_COUNTED_LIFECYCLE || SECURITY_ASSERT_ENABLED&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;inline&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;adopted&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(RefCountedBase* object)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!object)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ASSERT_WITH_SECURITY_IMPLICATION(!object-&amp;gt;m_deletionHasBegun);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; CHECK_REF_COUNTED_LIFECYCLE&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    object-&amp;gt;m_adoptionIsRequired = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;忽略其他障眼法，能够看到RefCountedBase类有一个类型为int的成员变量m_refCount，它就是用来描述对象的引用计数的。此外，RefCountedBase类还提供了两个成员函数ref和derefBase，分别用来增加和减少成员变量m_refCount描述的对象引用计数。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;调用RefCountedBase类的成员函数derefBase减少一个对象的引用计数时，如果减少后的引用计数等于0，那么它的返回值就等于true，表示该对象应该被释放了，不过这个释放的操作留给子类RefCounted实现。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从RefCountedBase类的构造函数可以看到，一个RefCountedBase类及其子类对象被创建出来的时候，它的引用计数值就已经被初始化为1，这意味着不需要额外调用RefCountedBase类的成员函数ref来增加新创建对象的引用计数。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这是RefCounted的基类，提供了引用计数的基本实现，接下来就看看子类RefCounted，同样位于external/chromium_org/third_party/WebKit/Source/wtf/RefCounted.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt; &lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; RefCounted : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; RefCountedBase &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    WTF_MAKE_NONCOPYABLE(RefCounted);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    WTF_MAKE_FAST_ALLOCATED;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;deref&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//调用了父类的derefBase函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (derefBase())&lt;span class=&quot;comment&quot;&gt;//如果返回true，就delete掉这个对象&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;T*&amp;gt;(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;ifdef&lt;/span&gt; ENABLE_INSTANCE_COUNTER&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    RefCounted()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        incrementInstanceCount&amp;lt;T&amp;gt;(&lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;T*&amp;gt;(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ~RefCounted()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        decrementInstanceCount&amp;lt;T&amp;gt;(&lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;T*&amp;gt;(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;else&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    RefCounted()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;RefCounted类有一个成员函数deref，它调用父类RefCountedBase类的成员函数derefBase减少对象的引用计数。当RefCountedBase类的成员函数derefBase的返回值等于true的时候，就表示对象该释放了，因此RefCounted类的成员函数deref就直接将它delete掉。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;RefCounted的基类RefCountedBase在增加或者减少引用计数的时候，并没有加锁或者执行原子加减操作。因此，我们就说RefCounted类是线程不安全的。如果我们需要线程安全版本的RefCounted类，WebKit提供了另外一个类ThreadSafeRefCounted，它继承于ThreadSafeRefCountedBase类。ThreadSafeRefCountedBase类位于external/chromium_org/third_party/WebKit/Source/wtf/ThreadSafeRefCounted.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; WTF_EXPORT ThreadSafeRefCountedBase &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    WTF_MAKE_NONCOPYABLE(ThreadSafeRefCountedBase);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    WTF_MAKE_FAST_ALLOCATED;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ThreadSafeRefCountedBase(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; initialRefCount = &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        : m_refCount(initialRefCount)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//原子操作保证线程安全&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        atomicIncrement(&amp;amp;m_refCount);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;hasOneRef&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; refCount() == &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;refCount&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;volatile&lt;/span&gt; &amp;amp;&amp;gt;(m_refCount);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Returns whether the pointer should be freed or not.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;derefBase&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        WTF_ANNOTATE_HAPPENS_BEFORE(&amp;amp;m_refCount);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//原子操作保证线程安全&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (atomicDecrement(&amp;amp;m_refCount) &amp;lt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            WTF_ANNOTATE_HAPPENS_AFTER(&amp;amp;m_refCount);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; m_refCount;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;与RefCountedBase类一样，ThreadSafeRefCountedBase类也实现了成员函数ref和derefBase，不过它通过原子操作atomicIncrement和atomicDecrement来分别增加和减少目标对象的引用计数，因此它是线程安全的。 ThreadSafeRefCounted类的实现如下，同样位于external/chromium_org/third_party/WebKit/Source/wtf/ThreadSafeRefCounted.h：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; T&amp;gt; &lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; ThreadSafeRefCounted : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; ThreadSafeRefCountedBase &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;deref&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (derefBase())&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;T*&amp;gt;(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ThreadSafeRefCounted()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;与RefCounted类一样，ThreadSafeRefCounted类也实现了成员函数deref，并且调用父类ThreadSafeRefCountedBase的成员函数derefBase减少对象的引用计数。当对象的引用计数小于等于0时，就会将它delete掉。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;有了RefCounted和ThreadSafeRefCounted这两个基类为对象提供计数功能之后，我们就继续分析第一类智能指针RefPtr的实现，位于external/chromium_org/third_party/WebKit/Source/wtf/RefPtr.h：&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;template&amp;lt;typename T&amp;gt; class RefPtr &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    WTF_DISALLOW_CONSTRUCTION_FROM_ZERO(RefPtr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    WTF_DISALLOW_ZERO_ASSIGNMENT(RefPtr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;public:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALWAYS_INLINE RefPtr() : m_ptr(0) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALWAYS_INLINE RefPtr(std::nullptr_t) : m_ptr(0) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALWAYS_INLINE RefPtr(T* ptr) : m_ptr(ptr) &amp;#123; refIfNotNull(ptr); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    template&amp;lt;typename U&amp;gt; RefPtr(const RawPtr&amp;lt;U&amp;gt;&amp;amp; ptr, EnsurePtrConvertibleArgDecl(U, T)) : m_ptr(ptr.get()) &amp;#123; refIfNotNull(m_ptr); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALWAYS_INLINE explicit RefPtr(T&amp;amp; ref) : m_ptr(&amp;amp;ref) &amp;#123; m_ptr-&amp;gt;ref(); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALWAYS_INLINE RefPtr(const RefPtr&amp;amp; o) : m_ptr(o.m_ptr) &amp;#123; refIfNotNull(m_ptr); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    template&amp;lt;typename U&amp;gt; RefPtr(const RefPtr&amp;lt;U&amp;gt;&amp;amp; o, EnsurePtrConvertibleArgDecl(U, T)) : m_ptr(o.get()) &amp;#123; refIfNotNull(m_ptr); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // See comments in PassRefPtr.h for an explanation of why this takes a const reference.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    template&amp;lt;typename U&amp;gt; RefPtr(const PassRefPtr&amp;lt;U&amp;gt;&amp;amp;, EnsurePtrConvertibleArgDecl(U, T));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // Hash table deleted values, which are only constructed and never copied or destroyed.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    RefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    bool isHashTableDeletedValue() const &amp;#123; return m_ptr == hashTableDeletedValue(); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALWAYS_INLINE ~RefPtr() &amp;#123; derefIfNotNull(m_ptr); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALWAYS_INLINE T* get() const &amp;#123; return m_ptr; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    void clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    PassRefPtr&amp;lt;T&amp;gt; release() &amp;#123; PassRefPtr&amp;lt;T&amp;gt; tmp = adoptRef(m_ptr); m_ptr = 0; return tmp; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    T&amp;amp; operator*() const &amp;#123; return *m_ptr; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALWAYS_INLINE T* operator-&amp;gt;() const &amp;#123; return m_ptr; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    bool operator!() const &amp;#123; return !m_ptr; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // This conversion operator allows implicit conversion to bool but not to other integer types.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    typedef T* (RefPtr::*UnspecifiedBoolType);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    operator UnspecifiedBoolType() const &amp;#123; return m_ptr ? &amp;amp;RefPtr::m_ptr : 0; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    RefPtr&amp;amp; operator=(const RefPtr&amp;amp;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    RefPtr&amp;amp; operator=(T*);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    RefPtr&amp;amp; operator=(const PassRefPtr&amp;lt;T&amp;gt;&amp;amp;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    RefPtr&amp;amp; operator=(std::nullptr_t) &amp;#123; clear(); return *this; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    template&amp;lt;typename U&amp;gt; RefPtr&amp;lt;T&amp;gt;&amp;amp; operator=(const RefPtr&amp;lt;U&amp;gt;&amp;amp;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    template&amp;lt;typename U&amp;gt; RefPtr&amp;lt;T&amp;gt;&amp;amp; operator=(const PassRefPtr&amp;lt;U&amp;gt;&amp;amp;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    template&amp;lt;typename U&amp;gt; RefPtr&amp;lt;T&amp;gt;&amp;amp; operator=(const RawPtr&amp;lt;U&amp;gt;&amp;amp;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    void swap(RefPtr&amp;amp;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    static T* hashTableDeletedValue() &amp;#123; return reinterpret_cast&amp;lt;T*&amp;gt;(-1); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;private:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    T* m_ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;注意，这里的模板参数T要么是从RefCounted的子类，要么是ThreadSafeRefCounted的子类。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;除了参数类型为T&amp;amp;的构造函数之外，RefPtr类的所有其它构造函数都会调用函数refIfNotNull来增加目标对象的引用计数。在参数类型为T&amp;amp;的构造函数中，能够保证参数ref不为NULL，因此就可以直接调用目标对象的成员函数ref来增加其引用计数。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;相应地，RefPtr类的析构函数会调用函数derefIfNotNull来减少目标对象的引用计数。这样就可以保证一个智能指针超出其生命周期时，能够自动释放它引用的对象。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;为了能够通过智能指针来调用目标对象的成员函数，RefPtr类实现了两个操作符重载成员函数*和-&amp;gt;。此外，RefPtr类还实现了一个成员函数get，用来获取一个指向目标对象的裸指针，这样就实现智能指针到裸指针的转换。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数refIfNotNull和derefIfNotNull的实现如下，位于external/chromium_org/third_party/WebKit/Source/wtf/PassRefPtr.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt; &lt;span class=&quot;function&quot;&gt;ALWAYS_INLINE &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;refIfNotNull&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(T* ptr)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (LIKELY(ptr != &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        requireAdoption(ptr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ptr-&amp;gt;ref();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt; &lt;span class=&quot;function&quot;&gt;ALWAYS_INLINE &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;derefIfNotNull&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(T* ptr)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (LIKELY(ptr != &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ptr-&amp;gt;deref();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数refIfNotNull和derefIfNotNull分别能过调用参数ptr描述的对象的成员函数ref和deref减少其引用计数。不过在增加和减少参数ptr描述的对象的引用计数之前，会先判断参数ptr的值是否等于0。只有在不等于0的情况下，才会执行增加和减少引用计数的操作。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;以上就是WebKit的第一类智能指针RefPtr的实现。&lt;/p&gt;
&lt;h2 id=&quot;去除无用引用计数&quot;&gt;&lt;a href=&quot;#去除无用引用计数&quot; class=&quot;headerlink&quot; title=&quot;去除无用引用计数&quot;&gt;&lt;/a&gt;去除无用引用计数&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在实际使用中，似乎没有什么问题。但是细心的同学可能会注意到，当智能指针作为参数或者返回值在函数之间传递时，都会执行一次加1的引用计数操作，而当参数或者返回值超出其生命周期时，又会对称地执行一次减1的引用计数操作。这些加1和减1的引用计数操作是否是必须的呢？我们可以看下面的例子：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;RefPtr&amp;lt;T2&amp;gt; foo(RefPtr&amp;lt;T1&amp;gt; p2) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    RefPtr&amp;lt;T2&amp;gt; p3 = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; T2();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; p3;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;RefPtr&amp;lt;T1&amp;gt; p1 = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; T1();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;RefPtr&amp;lt;T2&amp;gt; p4 = foo(p1);&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上述过程的引用计数计算如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;我们先new一个T1对象，并且通过它来构造智能指针p1时，这时候T1对象的引用计数为1，它不会被销毁。&lt;/li&gt;
&lt;li&gt;接下来我们以智能指针p1为参数调用函数foo，这时候智能指针p2也引用了T1对象，因此T1对象的引用计数增加为2，它也不会被销毁。&lt;/li&gt;
&lt;li&gt;从函数foo返回后，智能指针p2超出了其生命周期范围，因此T1对象的引用计数减少为1，它仍然是不会被销毁。&lt;/li&gt;
&lt;li&gt;要等到智能指针p1也超出其生命周期范围时，T1对象的引用计数才会减少为0，从而被释放。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;go on：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在函数foo内部，我们先new一个T2对象，并且通过它来构造智能指针p3，这时候T2对象的引用计数为1，它不会被销毁。&lt;/li&gt;
&lt;li&gt;接下来函数foo返回智能指针p3给智能指针p4，这时候智能指针p4也引用了T2对象，因此T2对象的引用计数增加为2，它也不会被销毁。&lt;/li&gt;
&lt;li&gt;与此同时，智能指针p3超出了其生命周期范围，因此T2对象的引用计数减少为1，它仍然是不会被销毁。&lt;/li&gt;
&lt;li&gt;同样是要等到智能指针p4也超出其生命周期范围时，T2对象的引用计数才会减少为0，从而被释放。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;很明显，在调用函数foo期间，完全是没有增加和减少T1对象和T2对象的引用计数的，这相当于是做了两次无用功。而且在实际的工程实践中，上述的代码是相当普通的，因此就会充斥着大量的无用功操作。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;为了去除上述的无用功，WebKit提供了另外一个智能指针类PassRefPtr，这个类定义在文件external/chromium_org/third_party/WebKit/Source/wtf/PassRefPtr.h中，它的实现如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;   template&amp;lt;typename T&amp;gt; class PassRefPtr &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       WTF_DISALLOW_CONSTRUCTION_FROM_ZERO(PassRefPtr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   public:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       PassRefPtr() : m_ptr(0) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       PassRefPtr(std::nullptr_t) : m_ptr(0) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       PassRefPtr(T* ptr) : m_ptr(ptr) &amp;#123; refIfNotNull(ptr); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       template&amp;lt;typename U&amp;gt; PassRefPtr(const RawPtr&amp;lt;U&amp;gt;&amp;amp; ptr, EnsurePtrConvertibleArgDecl(U, T)) : m_ptr(ptr.get()) &amp;#123; refIfNotNull(m_ptr); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       explicit PassRefPtr(T&amp;amp; ptr) : m_ptr(&amp;amp;ptr) &amp;#123; m_ptr-&amp;gt;ref(); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       // It somewhat breaks the type system to allow transfer of ownership out of&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       // a const PassRefPtr. However, it makes it much easier to work with PassRefPtr&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       // temporaries, and we don&#39;t have a need to use real const PassRefPtrs anyway.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       //我们是一个PassRefPtr智能指针p1构造另一个PassRefPtr智能指针p2时，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       //或者说将一个PassRefPtr智能指针p1传递给另一个PassRefPtr智能指针p2时，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       //智能指针p1就自动失去了对目标对象的引用，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       //并且这时候目标对象的引用计数没有发生变化。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       PassRefPtr(const PassRefPtr&amp;amp; o) : m_ptr(o.leakRef()) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       template&amp;lt;typename U&amp;gt; PassRefPtr(const PassRefPtr&amp;lt;U&amp;gt;&amp;amp; o, EnsurePtrConvertibleArgDecl(U, T)) : m_ptr(o.leakRef()) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       ALWAYS_INLINE ~PassRefPtr() &amp;#123; derefIfNotNull(m_ptr); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       template&amp;lt;typename U&amp;gt; PassRefPtr(const RefPtr&amp;lt;U&amp;gt;&amp;amp;, EnsurePtrConvertibleArgDecl(U, T));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       T* get() const &amp;#123; return m_ptr; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       T* leakRef() const WARN_UNUSED_RETURN;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       T&amp;amp; operator*() const &amp;#123; return *m_ptr; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       T* operator-&amp;gt;() const &amp;#123; return m_ptr; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       bool operator!() const &amp;#123; return !m_ptr; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       // This conversion operator allows implicit conversion to bool but not to other integer types.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       typedef T* (PassRefPtr::*UnspecifiedBoolType);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       operator UnspecifiedBoolType() const &amp;#123; return m_ptr ? &amp;amp;PassRefPtr::m_ptr : 0; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       friend PassRefPtr adoptRef&amp;lt;T&amp;gt;(T*);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   private:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       enum AdoptRefTag &amp;#123; AdoptRef &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       PassRefPtr(T* ptr, AdoptRefTag) : m_ptr(ptr) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       PassRefPtr&amp;amp; operator=(const PassRefPtr&amp;amp;) &amp;#123; COMPILE_ASSERT(!sizeof(T*), PassRefPtr_should_never_be_assigned_to); return *this; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       mutable T* m_ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;template&amp;lt;typename T&amp;gt; template&amp;lt;typename U&amp;gt; inline PassRefPtr&amp;lt;T&amp;gt;::PassRefPtr(const RefPtr&amp;lt;U&amp;gt;&amp;amp; o, EnsurePtrConvertibleArgDefn(U, T))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       : m_ptr(o.get())&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       T* ptr = m_ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       refIfNotNull(ptr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   //leakRef函数回抹去参数指针对象的引用，强行赋值为0（NULL）&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   //此时它就就自动失去了对目标对象的引用，但是用于构造另一个只能指针的refCount还不变&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   template&amp;lt;typename T&amp;gt; inline T* PassRefPtr&amp;lt;T&amp;gt;::leakRef() const&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       T* ptr = m_ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       m_ptr = 0;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       return ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从PassRefPtr类的构造函数可以知道，当它们的参数是T&lt;em&gt;、T&amp;amp;和const RefPtr&lt;t&gt;&amp;amp;时，PassRefPtr类描述的智能指针与RefPtr类描述的智能指针并没有什么区别。&lt;em&gt;*但是当参数为const PassRefPtr&lt;t&gt;&amp;amp;时，也就是我们是一个PassRefPtr智能指针p1构造另一个PassRefPtr智能指针p2时，或者说将一个PassRefPtr智能指针p1传递给另一个PassRefPtr智能指针p2时，神奇的事情就发生了！智能指针p1就自动失去了对目标对象的引用，并且这时候目标对象的引用计数没有发生变化。&lt;/t&gt;&lt;/em&gt;&lt;/t&gt;&lt;/em&gt;这是通过PassRefPtr类的成员函数leakRef实现的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;有了PassRefPtr类之后，我们再来改写上面举的例子，如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;PassRefPtr&amp;lt;T2&amp;gt; foo(PassRefPtr&amp;lt;T1&amp;gt; p2) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    PassRefPtr&amp;lt;T2&amp;gt; p3 = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; T2();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; p3;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;PassRefPtr&amp;lt;T1&amp;gt; p1 = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; T1();&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;此时执行上述代码对于引用计数会有稍许变化：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1. T1对象和T2对象在函数foo的调用或者返回前后，它们的引用计数值都始终保持为1。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;只有当智能指针p1和智能指针p4超出其生命周期范围时，T1对象和T2对象的引用计数才会减少为0，从而被释放。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这样就可以免去智能指针作为参数或者返回值传递目标对象的增加和减少引用计数操作，从而去掉无用功。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从前面PassRefPtr类的定义可以知道，我们可以将一个RefPtr智能指针传递给一个PassRefPtr智能指针，这时候目标对象的引用计数会增加1。我们还可以另外一种方式将一个RefPtr智能指针传递给一个PassRefPtr智能指针。这种传递方式将会使得目标对象的引用计数不发生变化，并且RefPtr智能指针自动失去对目标对象的引用。这是通过调用RefPtr类的成员函数release实现的，这个函数定义在文件external/chromium_org/third_party/WebKit/Source/wtf/RefPtr.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;namespace&lt;/span&gt; WTF &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt; &lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; RefPtr &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PassRefPtr&amp;lt;T&amp;gt; release() &amp;#123; PassRefPtr&amp;lt;T&amp;gt; tmp = adoptRef(m_ptr); m_ptr = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; tmp; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        T* m_ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;RefPtr类的成员函数release调用函数adoptRef来构造一个PassRefPtr智能指针，  这个函数定义在文件external/chromium_org/third_party/WebKit/Source/wtf/PassRefPtr.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;namespace&lt;/span&gt; WTF &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt; &lt;span class=&quot;keyword&quot;&gt;inline&lt;/span&gt; PassRefPtr&amp;lt;T&amp;gt; adoptRef(T* p)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; PassRefPtr&amp;lt;T&amp;gt;(p, PassRefPtr&amp;lt;T&amp;gt;::AdoptRef);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数adoptRef调用以下的PassRefPtr类的构造函数来构造一个PassRefPtr智能指针，这个函数定义在文件external/chromium_org/third_party/WebKit/Source/wtf/PassRefPtr.h中:&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;namespace&lt;/span&gt; WTF &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt; &lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; PassRefPtr &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;enum&lt;/span&gt; AdoptRefTag &amp;#123; AdoptRef &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PassRefPtr(T* ptr, AdoptRefTag) : m_ptr(ptr) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;mutable&lt;/span&gt; T* m_ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从这里就可以看到，上述的PassRefPtr类的构造函数并没有增加目标对象的引用计数，因此我们就可以在不改变目标对象的引用计数的前提下，将一个RefPtr智能指针传递给一个PassRefPtr智能指针，相当于就是将一个RefPtr智能指针对目标对象的所有权转移给一个PassRefPtr智能指针。&lt;/p&gt;
&lt;h2 id=&quot;第二类智能指针&quot;&gt;&lt;a href=&quot;#第二类智能指针&quot; class=&quot;headerlink&quot; title=&quot;第二类智能指针&quot;&gt;&lt;/a&gt;第二类智能指针&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接下来我们再看WebKit的第二类智能指针的实现，它由类OwnPtr实现，这个类定义在文件external/chromium_org/third_party/WebKit/Source/wtf/OwnPtr.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;96&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;97&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;98&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;99&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;100&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;101&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;102&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;103&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;104&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;105&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;106&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;107&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;108&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;109&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;110&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;111&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;112&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;113&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;114&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;115&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;116&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;117&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;118&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;119&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;120&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;121&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;122&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;123&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;124&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;125&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;126&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;namespace&lt;/span&gt; WTF &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//.......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt; &lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; OwnPtr &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; RemoveExtent&amp;lt;T&amp;gt;::Type ValueType;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; ValueType* PtrType;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OwnPtr() : m_ptr(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OwnPtr(&lt;span class=&quot;built_in&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;keyword&quot;&gt;nullptr_t&lt;/span&gt;) : m_ptr(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OwnPtr(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; PassOwnPtr&amp;lt;T&amp;gt;&amp;amp;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; !COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OwnPtr(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; OwnPtr&amp;amp;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ~OwnPtr()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            OwnedPtrDeleter&amp;lt;T&amp;gt;::deletePtr(m_ptr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            m_ptr = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;function&quot;&gt;PtrType &lt;span class=&quot;title&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;/span&gt;&amp;#123; &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; m_ptr; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PassOwnPtr&amp;lt;T&amp;gt; release();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;function&quot;&gt;PtrType &lt;span class=&quot;title&quot;&gt;leakPtr&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; WARN_UNUSED_RETURN&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ValueType&amp;amp; &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt;*() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123; ASSERT(m_ptr); &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; *m_ptr; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PtrType &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt;-&amp;gt;() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123; ASSERT(m_ptr); &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; m_ptr; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OwnPtr&amp;amp; &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt;=(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; PassOwnPtr&amp;lt;T&amp;gt;&amp;amp;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OwnPtr(OwnPtr&amp;amp;&amp;amp;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OwnPtr&amp;amp; &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt;=(OwnPtr&amp;amp;&amp;amp;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; !COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// If rvalue references are supported, noncopyable takes care of this.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OwnPtr&amp;amp; &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt;=(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; OwnPtr&amp;amp;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PtrType m_ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt; &lt;span class=&quot;keyword&quot;&gt;inline&lt;/span&gt; OwnPtr&amp;lt;T&amp;gt;::OwnPtr(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; PassOwnPtr&amp;lt;T&amp;gt;&amp;amp; o)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        : m_ptr(o.leakPtr())&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt; &lt;span class=&quot;keyword&quot;&gt;inline&lt;/span&gt; PassOwnPtr&amp;lt;T&amp;gt; OwnPtr&amp;lt;T&amp;gt;::release()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PtrType ptr = m_ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        m_ptr = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; PassOwnPtr&amp;lt;T&amp;gt;(ptr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt; &lt;span class=&quot;keyword&quot;&gt;inline&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; OwnPtr&amp;lt;T&amp;gt;::PtrType OwnPtr&amp;lt;T&amp;gt;::leakPtr()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PtrType ptr = m_ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        m_ptr = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt; &lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; U&amp;gt; &lt;span class=&quot;keyword&quot;&gt;inline&lt;/span&gt; OwnPtr&amp;lt;T&amp;gt;&amp;amp; OwnPtr&amp;lt;T&amp;gt;::&lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt;=(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; PassOwnPtr&amp;lt;U&amp;gt;&amp;amp; o)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PtrType ptr = m_ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        m_ptr = o.leakPtr();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ASSERT(!ptr || m_ptr != ptr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OwnedPtrDeleter&amp;lt;T&amp;gt;::deletePtr(ptr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; *&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt; &lt;span class=&quot;keyword&quot;&gt;inline&lt;/span&gt; OwnPtr&amp;lt;T&amp;gt;::OwnPtr(OwnPtr&amp;lt;T&amp;gt;&amp;amp;&amp;amp; o)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        : m_ptr(o.leakPtr())&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt; &lt;span class=&quot;keyword&quot;&gt;inline&lt;/span&gt; OwnPtr&amp;lt;T&amp;gt;&amp;amp; OwnPtr&amp;lt;T&amp;gt;::&lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt;=(OwnPtr&amp;lt;T&amp;gt;&amp;amp;&amp;amp; o)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PtrType ptr = m_ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        m_ptr = o.leakPtr();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ASSERT(!ptr || m_ptr != ptr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OwnedPtrDeleter&amp;lt;T&amp;gt;::deletePtr(ptr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; *&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125; &lt;span class=&quot;comment&quot;&gt;// namespace WTF&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从OwnPtr类的定义可以看到，OwnPtr智能指针只能通过以下构造函数创建：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt; &lt;span class=&quot;keyword&quot;&gt;inline&lt;/span&gt; OwnPtr&amp;lt;T&amp;gt;::OwnPtr(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; PassOwnPtr&amp;lt;T&amp;gt;&amp;amp; o)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        : m_ptr(o.leakPtr())&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;也就是说，我们创建了一个T对象后，只能先用来创建一个PassOwnPtr对象，然后再用该PassOwnPtr对象来创建一个OwnPtr智能指针。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当然，我们也可以使用OwnPtr类的以下构造函数来创建一个没有引用任何目标对象的OwnPtr智能指针：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;OwnPtr() : m_ptr(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;OwnPtr(&lt;span class=&quot;built_in&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;keyword&quot;&gt;nullptr_t&lt;/span&gt;) : m_ptr(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后，再通过调用操作符重载函数operator=将一个PassOwnPtr对象赋值给OwnPtr智能指针：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt; &lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; U&amp;gt; &lt;span class=&quot;keyword&quot;&gt;inline&lt;/span&gt; OwnPtr&amp;lt;T&amp;gt;&amp;amp; OwnPtr&amp;lt;T&amp;gt;::&lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt;=(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; PassOwnPtr&amp;lt;U&amp;gt;&amp;amp; o)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//对目标对象的引用从PassOwnPtr智能指针转移到了OwnPtr智能指针&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PtrType ptr = m_ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        m_ptr = o.leakPtr();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//对象与参数o描述的PassOwnPtr智能指针引用的目标对象是不一样的，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//并且该对象会被释放掉。&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ASSERT(!ptr || m_ptr != ptr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OwnedPtrDeleter&amp;lt;T&amp;gt;::deletePtr(ptr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; *&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;无论是哪一种方式创建OwnPtr智能指针，都必须先创建一个PassOwnPtr对象。PassOwnPtr类描述的也是一个智能指针，它与OwnPtr的关系有点类似我前面分析的RefPtr与PassRefPtr的关系。也就是说，PassOwnPtr智能指针可以作为函数参数或者函数返回值传递。后面我们再详细分析PassOwnPtr智能指针的创建过程。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;PassOwnPtr类有一个成员函数leakPtr，它的作用类似于前面分析的PassRefPtr类的成员函数leakPtr，都是用来放弃一个PassOwnPtr智能指针对目标对象的引用的。在上面描述的两种OwnPtr智能指针创建方式中，被PassOwnPtr智能指针放弃引用的目标对象将被正在创建的OwnPtr智能指针接管。也就是说，对目标对象的引用从PassOwnPtr智能指针转移到了OwnPtr智能指针。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;不过对于通过操作符重载函数operator=创建的OwnPtr智能指针，如果它之前有引用其它的目标对象，那么就要求该对象与参数o描述的PassOwnPtr智能指针引用的目标对象是不一样的，并且该对象会被释放掉。也就是说，当一个OwnPtr智能指针要引用新的目标对象时，必须先释放之前引用的旧目标对象。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;一个OwnPtr智能指针在超出其生命周期范围之前，如果想要放弃对目标对象的引用，那么可以通过调用OwnPtr类的成员函数release或者leakPtr来实现，如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt; &lt;span class=&quot;keyword&quot;&gt;inline&lt;/span&gt; PassOwnPtr&amp;lt;T&amp;gt; OwnPtr&amp;lt;T&amp;gt;::release()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PtrType ptr = m_ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        m_ptr = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; PassOwnPtr&amp;lt;T&amp;gt;(ptr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt; &lt;span class=&quot;keyword&quot;&gt;inline&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; OwnPtr&amp;lt;T&amp;gt;::PtrType OwnPtr&amp;lt;T&amp;gt;::leakPtr()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PtrType ptr = m_ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        m_ptr = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;OwnPtr类的成员函数release将OwnPtr智能指针放弃引用的目标对象转移给了一个PassOwnPtr智能指针，这意味着可以将一个OwnPtr智能指针转化为一个PassOwnPtr指针，从而使得它引用的目标对象可以作为函数参数或者函数返回值传递。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;OwnPtr类的成员函数leakPtr是直接放弃OwnPtr智能指针引用的目标对象，不过它会返回该目标对象的地址值给调用者，也就是将一个指向目标对象的裸指针返回给调用者。&lt;/p&gt;
&lt;h2 id=&quot;Move语意&quot;&gt;&lt;a href=&quot;#Move语意&quot; class=&quot;headerlink&quot; title=&quot;Move语意&quot;&gt;&lt;/a&gt;Move语意&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们注意到，OwnPtr类的成员函数leakPtr的返回值类型为OwnPtr&lt;t&gt;::PtrType，它的定义如下所示：&lt;/t&gt;&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; RemoveExtent&amp;lt;T&amp;gt;::Type ValueType;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; ValueType* PtrType;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; RemoveExtent是一个与C++ 11引入的右值引用（Rvalue Reference）有关一个模板类。右值引用通过T&amp;amp;&amp;amp;符号来表示，它主要是用来实现move语意和完美转发（perfect forwarding）。关于右值引用的概念，由于篇幅关系，这里不进行展开，然后强烈建议大家去看看这两篇文章：&lt;a href=&quot;https://www.cnblogs.com/qicosmos/p/4283455.html&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;从4行代码看右值引用&lt;/a&gt;和&lt;a href=&quot;https://docs.microsoft.com/en-us/cpp/cpp/rvalue-reference-declarator-amp-amp?view=vs-2017&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Rvalue Reference Declarator: &amp;amp;&amp;amp;&lt;/a&gt;。这里我们只需要知道，ValueType描述的是模板参数T的值类型，而PtrType描述的是模板参数T的裸指针类型，不管我们是使用T、T&amp;amp;还是T&amp;amp;&amp;amp;来推导模板参数。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;关于右值引用的move语意，这里值得再解释一下。简单地说，move语意是为了消除临时对象之间的拷贝操作，例如，对于以下表达式来说：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;built_in&quot;&gt;string&lt;/span&gt; s = &lt;span class=&quot;built_in&quot;&gt;string&lt;/span&gt;(&lt;span class=&quot;string&quot;&gt;&quot;h&quot;&lt;/span&gt;) + &lt;span class=&quot;string&quot;&gt;&quot;e&quot;&lt;/span&gt; + &lt;span class=&quot;string&quot;&gt;&quot;ll&quot;&lt;/span&gt; + &lt;span class=&quot;string&quot;&gt;&quot;o&quot;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;string(“h”)会产生一个临时对象。这个临时对象与”e”相加后，又会产生另外一个临时对象。依次类推，直到”o”相加完成之后。而且最后生成的临时对象又会被拷贝给字符串s。这些中间的临时对象都是没有必要生成的，而且字符串s也不需要去拷贝最后生成的临时对象得到。我们完全可以只生成一个临时对象，也就是由string(“h”)产生一个临时对象，此后直接将后面的”e”、”ll”和”o”追加在此临时对象内部的字符缓冲区上，并且最后将该临时对象内部所拥有的字符缓冲区转移给字符串s。这样就可以在一定程度上提高字符串的连接效率，而这就是所谓的move语意，它是与copy意义相对的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;一个类要实现move语意，必须要提供move构造函数和move赋值操作符函数，就好像一个类要实现copy语意，要提供copy构造函数copy赋值操作符函数一样，只不过编译器不会为一个类提供默认的move构造函数和move赋值操作符函数。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们看到，在编译器支持右值引用的情况下，OwnPtr类实现了move构造函数和move赋值操作符函数，如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt; &lt;span class=&quot;keyword&quot;&gt;inline&lt;/span&gt; OwnPtr&amp;lt;T&amp;gt;::OwnPtr(OwnPtr&amp;lt;T&amp;gt;&amp;amp;&amp;amp; o)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        : m_ptr(o.leakPtr())&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt; &lt;span class=&quot;keyword&quot;&gt;inline&lt;/span&gt; OwnPtr&amp;lt;T&amp;gt;&amp;amp; OwnPtr&amp;lt;T&amp;gt;::&lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt;=(OwnPtr&amp;lt;T&amp;gt;&amp;amp;&amp;amp; o)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PtrType ptr = m_ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        m_ptr = o.leakPtr();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ASSERT(!ptr || m_ptr != ptr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OwnedPtrDeleter&amp;lt;T&amp;gt;::deletePtr(ptr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; *&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;一个类实现的move构造函数和move赋值操作符函数的参数必须是一个右值引用，并且它们的作用是将一个对象拥有的资源转移给另外一个对象。以OwnPtr类为例，一个OwnPtr智能指针拥有的资源就是对目标对象的引用，也就是它的的move构造函数和move赋值操作符函数的作用是将一个OwnPtr智能指针引用的目标对象转移给另外一个OwnPtr智能指针引用。这样就既不违反我们前面说的一个目标对象在同一时刻只能被一个第二类智能指针引用的原则，同时又能够实现OwnPtr类的move语意。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;同时，我们也可以看到，在编译器不支持右值引用的情况下，OwnPtr类只是声明了copy构造函数copy赋值操作符函数，但是没有实现它们。这就意味着，我们不能将一个OwnPtr智能指针拷贝给另外一个，因为这会违反我们前面说的一个目标对象在同一时刻只能被一个第二类智能指针引用的原则。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;与前面分析的RefPtr和PassRefPtr智能指针类似，OwnPtr智能指针也提供了两个成员操作符重载函数operator*和operator-&amp;gt;来直接操作目标对象，例如调用目标对象的成员函数，如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;ValueType&amp;amp; &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt;*() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123; ASSERT(m_ptr); &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; *m_ptr; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;PtrType &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt;-&amp;gt;() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123; ASSERT(m_ptr); &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; m_ptr; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当一个OwnPtr智能指针超出其生命周期范围内时，它所引用的对象就会被释放掉，如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;~OwnPtr()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    OwnedPtrDeleter&amp;lt;T&amp;gt;::deletePtr(m_ptr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    m_ptr = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从而就可以起到自动释放不再需要的对象的作用。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从这里可以看到，OwnPtr智能指针是通过模板类OwnedPtrDeleter&amp;lt; T &amp;gt;的成员函数deletePtr来释放目标对象的，这个函数定义在文件external/chromium_org/third_party/WebKit/Source/wtf/OwnPtrCommon.h中，它的实现如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; OwnedPtrDeleter &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;deletePtr&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(T* ptr)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        COMPILE_ASSERT(!IsRefCounted&amp;lt;T&amp;gt;::value, UseRefPtrForRefCountedObjects);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        COMPILE_ASSERT(&lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(T) &amp;gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, TypeMustBeComplete);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;delete&lt;/span&gt; ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;模板类OwnedPtrDeleter&lt;t&gt;的成员函数deletePtr在编译时会通过宏COMPILE_ASSERT来断言参数ptr描述的对象不是从前面我们分析的RefCountedBase类或者ThreadSafeRefCountedBase继承下来的。这意味着OwnPtr智能指针不能用来引用具有引用计数功能的对象。&lt;/t&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这实际上是定义了这样的一个规则：&lt;strong&gt;具有引用计数功能的对象，如果要配合智能指针使用，那么就使用RefPtr或者PassRefPtr智能指针；否则的话，就使用OwnPtr或者我们接下来分析的PassOwnPtr智能指针。&lt;/strong&gt;这个规则要求我们对程序里面实现的类有一个清晰的设计。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;宏COMPILE_ASSERT实际上是利用C++ 11引入的static_assert特性来实现的。这个static_assert语句不会对编译后得到的二进制代码有任何影响，纯粹是编译期间使用的，用来在编译期间就能捕捉到错误。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从模板类OwnedPtrDeleter&amp;lt; T &amp;gt;的成员函数deletePtr的实现可以知道，当模板类IsRefCounted&lt;t&gt;的静态成员变量value的值等于true的时候，就说明参数ptr描述的对象是从RefCountedBase类或者ThreadSafeRefCountedBase继承下来的。&lt;/t&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;模板类IsRefCounted&amp;lt; T &amp;gt;的静态成员变量value的定义如下所示，这个成员变量定义在文件external/chromium_org/third_party/WebKit/Source/wtf/OwnPtrCommon.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; IsRefCounted &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; value = IsSubclass&amp;lt;T, RefCountedBase&amp;gt;::value&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        || IsSubclass&amp;lt;T, ThreadSafeRefCountedBase&amp;gt;::value;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从这里就可以看到，如果模板参数T是从RefCountedBase类或者ThreadSafeRefCountedBase类继承下来的，那么模板类IsRefCounted&amp;lt; T &amp;gt;的静态成员变量value就会等于true。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;判断模板参数T是不是从RefCountedBase类或者ThreadSafeRefCountedBase类继承下来，是通过调用模板类IsSubclass&amp;lt; T &amp;gt;的静态成员变量value来实现的。模板类IsSubclass&amp;lt; T &amp;gt;的静态成员变量value的定义如下所示，这个成员变量定义在文件external/chromium_org/third_party/WebKit/Source/wtf/TypeTraits.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;namespace&lt;/span&gt; WTF &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T, &lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; U&amp;gt; &lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; IsSubclass &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; YesType;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; NoType &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; padding[&lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; YesType &lt;span class=&quot;title&quot;&gt;subclassCheck&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(U*)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; NoType &lt;span class=&quot;title&quot;&gt;subclassCheck&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(...)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; T* t;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; value = &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(subclassCheck(t)) == &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(YesType);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//......&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里的模板参数U就为RefCountedBase或者ThreadSafeRefCountedBase，判断模板参数T是不是它们的子类用了一个很巧妙方法。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;模板类IsSubclass&amp;lt; T &amp;gt;定义了两个版本的静态成员函数subclassCheck，其中一个的参数为U&lt;em&gt;，另一个的参数为可变参数。如果T是从U继承下来的，T&lt;/em&gt;就可以自动转化为U&lt;em&gt;，这意味着调用静态成员函数subclassCheck(t)，也就subclassCheck(T&lt;/em&gt;)，会自动匹配为参数为U&lt;em&gt;的成员函数subclassCheck。参数为U&lt;/em&gt;的成员函数的返回值为YesType，这就意味着参数T是参数U的子类。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;注意，sizeof是一个编译器运算符号，当它的参数是一个函数的时候，实际上计算的是该函数的返回值的类型所占据的字节数。由于函数的返回值类型通过声明就可以知道，因此模板类IsSubclass&lt;t&gt;就只是声明了静态成员函数subclassCheck，而没有对应的实现。&lt;/t&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;前面提到，为了创建OwnPtr智能指针，我们首先要创建PassOwnPtr智能指针。PassOwnPtr智能指针使得OwnPtr智能指针引用的对象也可以作为函数参数或者函数返回值传递，它的定义如下所示，这个类定义在文件external/chromium_org/third_party/WebKit/Source/wtf/PassOwnPtr.h：&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;namespace WTF &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    template&amp;lt;typename T&amp;gt; class PassOwnPtr &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    public:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        typedef typename RemoveExtent&amp;lt;T&amp;gt;::Type ValueType;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        typedef ValueType* PtrType;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PassOwnPtr() : m_ptr(0) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PassOwnPtr(std::nullptr_t) : m_ptr(0) &amp;#123; &amp;#125;      &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PassOwnPtr(const PassOwnPtr&amp;amp; o) : m_ptr(o.leakPtr()) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ~PassOwnPtr() &amp;#123; OwnedPtrDeleter&amp;lt;T&amp;gt;::deletePtr(m_ptr); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PtrType get() const &amp;#123; return m_ptr; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PtrType leakPtr() const WARN_UNUSED_RETURN;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ValueType&amp;amp; operator*() const &amp;#123; ASSERT(m_ptr); return *m_ptr; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PtrType operator-&amp;gt;() const &amp;#123; ASSERT(m_ptr); return m_ptr; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        template&amp;lt;typename U&amp;gt; friend PassOwnPtr&amp;lt;U&amp;gt; adoptPtr(U*);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    private:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        explicit PassOwnPtr(PtrType ptr) : m_ptr(ptr) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mutable PtrType m_ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    template&amp;lt;typename T&amp;gt; inline typename PassOwnPtr&amp;lt;T&amp;gt;::PtrType PassOwnPtr&amp;lt;T&amp;gt;::leakPtr() const&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PtrType ptr = m_ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        m_ptr = 0;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        return ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    template&amp;lt;typename T&amp;gt; inline PassOwnPtr&amp;lt;T&amp;gt; adoptPtr(T* ptr)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        return PassOwnPtr&amp;lt;T&amp;gt;(ptr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;PassOwnPtr类的实现与OwnPtr类的实现是类似的，最主要的区别在于两点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;PassOwnPtr类提供了一个拷贝构造函数，通过此拷贝构造函数可以用一个PassOwnPtr智能指针构造另外一个PassOwnPtr智能指针，不过这样会导致原来的PassOwnPtr智能指针失去对目标对象的引用，因为目标对象转为被新构造的PassOwnPtr智能指针引用了。这意味着PassOwnPtr智能指针可以用来传递它所引用的目标对象。&lt;/li&gt;
&lt;li&gt;PassOwnPtr类有一个友员函数adoptPtr，通过这个友元函数可以调用PassOwnPtr类的一个私有构造函数为一个目标对象创建一个PassOwnPtr智能指针。这意味PassOwnPtr智能指针可以直接引用一个目标对象，而不像OwnPtr智能指针要通过另外一个PassOwnPtr智能指针来引用一个目标对象。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;以上就是WebKit实现的第一类智能指针RefPtr/PassRefPtr和第二类智能指针OwnPtr/PassOwnPtr，接下来我们继续分析WebKit实现的弱智能指针。&lt;/p&gt;
&lt;h2 id=&quot;弱智能指针&quot;&gt;&lt;a href=&quot;#弱智能指针&quot; class=&quot;headerlink&quot; title=&quot;弱智能指针&quot;&gt;&lt;/a&gt;弱智能指针&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WebKit的弱智能指针由WeakPtr类实现，这个类定义在文件external/chromium_org/third_party/WebKit/Source/wtf/WeakPtr.h中，如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; WeakPtr &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    WeakPtr(PassRefPtr&amp;lt;WeakReference&amp;lt;T&amp;gt; &amp;gt; ref) : m_ref(ref) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;T* &lt;span class=&quot;title&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;/span&gt;&amp;#123; &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; m_ref ? m_ref-&amp;gt;get() : &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;&amp;#123; m_ref.clear(); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    RefPtr&amp;lt;WeakReference&amp;lt;T&amp;gt; &amp;gt; m_ref;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从WeakPtr类的构造函数可以知道，创建一个WeakPtr弱智能指针需要一个WeakReference对象。这个WeakReference对象就保存在WeakPtr类的成员变量m_ref中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在使用一个WeakPtr弱智能指针，首先要调用它的成员函数get检查它引用的目标对象是否还存在。如果存在，WeakPtr类的成员函数get就会返回一个指向目标对象的指针给调用者。否则的话，WeakPtr类的成员函数get返回一个空指针。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WeakPtr类的成员函数get又是通过成员变量m_ref描述的一个WeakReference对象的成员函数get检查一个WeakPtr智能指针引用的目标对象是否还存在的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WeakReference类的实现如下所示，这个类定义在文件external/chromium_org/third_party/WebKit/Source/wtf/WeakPtr.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;template&amp;lt;typename T&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;class WeakReference : public ThreadSafeRefCounted&amp;lt;WeakReference&amp;lt;T&amp;gt; &amp;gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;public:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    static PassRefPtr&amp;lt;WeakReference&amp;lt;T&amp;gt; &amp;gt; create(T* ptr) &amp;#123; return adoptRef(new WeakReference(ptr)); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    static PassRefPtr&amp;lt;WeakReference&amp;lt;T&amp;gt; &amp;gt; createUnbound() &amp;#123; return adoptRef(new WeakReference()); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    T* get() const&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        return m_ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    void clear()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        m_ptr = 0;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    void bindTo(T* ptr)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        m_ptr = ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;private:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    WeakReference() : m_ptr(0) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    explicit WeakReference(T* ptr)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        : m_ptr(ptr)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;          ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    T* m_ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WeakReference类的成员变量m_ptr保存的就是一个WeakPtr弱智能指针所引用的目标对象的地址值。由于WeakPtr弱智能指针所引用的目标对象有可能是已经被销毁了的，因此WeakReference类的成员变量m_ptr保存的可能是一个无效的地址值。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们可以通过两种方式创建一个WeakReference对象。第一种方式是提供一个目标对象T，然后调用WeakReference类的静态成员函数create来创建。第二种方式是先调用WeakReference类的静态成员函数createUnbound创建一个成员变量m_ptr被初始化0的WeakReference对象，然后再调用该WeakReference对象的成员函数bindTo将成员变量m_ptr指向一个目标对象。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;前面提到，一个WeakPtr弱智能指针引用的目标对象有可能是已经被销毁了的。当这种情况发生时，我们需要调用与该WeakPtr弱智能指针与关联的WeakReference对象的成员函数clear，将其成员变量m_ptr的值设置为0。这样以后我们调用该WeakReference对象的成员函数get时，就会得到一个0值。也就是说，当一个WeakPtr弱智能指针引用的目标对象有可能被销毁之后，我们调用它的成员函数get获得的返回值是等于0的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;那么我们是怎么知道一个WeakPtr弱智能指针引用的目标对象正在被销毁的呢？要回答这个问题，我们首先观察WeakPtr弱智能指针是如何使用的。一般来说，如果某一个类的对象可以配合WeakPtr弱智能指针来引用，那么该类在定义时，就需要引入一个类型为WeakPtrFactory的成员变量，如以下的HTMLDocumentParser类所示，external/chromium_org/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; HTMLDocumentParser :  &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; ScriptableDocumentParser, &lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt; HTMLScriptRunnerHost &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    HTMLDocumentParser(HTMLDocument&amp;amp;, &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; reportErrors);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    WeakPtrFactory&amp;lt;HTMLDocumentParser&amp;gt; m_weakFactory;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在创建一个HTMLDocumentParser对象的时候，它的成员变量m_weakFactory就会被初始化，如下所示，这个函数定义在文件external/chromium_org/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;HTMLDocumentParser::HTMLDocumentParser(HTMLDocument&amp;amp; document, &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; reportErrors)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    : ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    , m_weakFactory(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WeakPtrFactory类的定义如下所示，这个类定义在文件external/chromium_org/third_party/WebKit/Source/wtf/WeakPtr.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;template&amp;lt;typename T&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;class WeakPtrFactory &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;public:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    explicit WeakPtrFactory(T* ptr) : m_ref(WeakReference&amp;lt;T&amp;gt;::create(ptr)) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    WeakPtrFactory(PassRefPtr&amp;lt;WeakReference&amp;lt;T&amp;gt; &amp;gt; ref, T* ptr)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        : m_ref(ref)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        m_ref-&amp;gt;bindTo(ptr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ~WeakPtrFactory() &amp;#123; m_ref-&amp;gt;clear(); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // We should consider having createWeakPtr populate m_ref the first time createWeakPtr is called.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    WeakPtr&amp;lt;T&amp;gt; createWeakPtr() &amp;#123; return WeakPtr&amp;lt;T&amp;gt;(m_ref); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;private:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    RefPtr&amp;lt;WeakReference&amp;lt;T&amp;gt; &amp;gt; m_ref;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;回到前面HTMLDocumentParser类的构造函数中，当一个HTMLDocumentParser对象创建时，它的地址值就会作为参数传递给WeakPtrFactory类的以T*为参数的构造函数，以便可以创建一个WeakPtrFactory对象。这个构造函数再以该HTMLDocumentParser对象的地址值为参数，调用WeakReference类的静态成员函数create创建一个WeakReference对象，保存在WeakPtrFactory类的成员变量m_ref中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当然我们也可以调用WeakPtrFactory类的另外一个构造函数创建一个WeakPtrFactory对象，不过我们需要提供一个WeakReference对象，以及一个目标对象的地址。在这种情况下，WeakPtrFactory类的构造函数除了会将调用者提供的WeakReference对象保存在成员变量m_ref之外，还会将目标对象的地址绑定到调用者提供的WeakReference对象中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;创建好一个WeakPtrFactory对象之后，就可以调用它的成员函数createWeakPtr获取一个WeakPtr弱智能指针了，获取到的WeakPtr弱智能指针是根据WeakPtrFactory对象的成员变量m_ref描述的WeakReference对象创建的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当一个WeakPtr弱智能指针引用的目标对象被销毁时，例如当一个HTMLDocumentParser对象被销毁时，它的成员变量m_weakFactory描述的WeakPtrFactory对象也会随之销毁，而当一个WeakPtrFactory对象被销毁时，它的析构函数就会被调用，随后这个WeakPtrFactory对象的成员变量m_ref描述的一个WeakReference对象的成员函数clear也会被调用，最后就会导致该WeakReference对象的成员变量m_ptr的值设置为0。这就意味着当一个WeakPtr弱智能指针引用的目标对象被销毁时，与它关联的一个WeakReference对象的成员变量m_ptr的值就会被设置为0，因此这时候调用该WeakPtr弱智能指针的成员函数get，就会获得一个0值。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;以上就是WebKit的弱智能指针的实现原理，它的核心就是通过组合方式给目标对象关联一个类型为WeakPtrFactory的成员变量，使得目标对象销毁时，该成员变量指向的WeakPtrFactory对象被析构。一个WeakPtrFactory对象在析构的过程中，又会将其内部的一个WeakReference对象的成员变量m_ptr的值设置为0。由于该WeakReference对象又是与WeakPtr弱智能指针关联的，因此WeakPtr弱智能指针通过该WeakReference对象的成员变量m_ptr就可以知道它所引用的目标是否已经被销毁。&lt;/p&gt;
&lt;h1 id=&quot;Chromium智能指针&quot;&gt;&lt;a href=&quot;#Chromium智能指针&quot; class=&quot;headerlink&quot; title=&quot;Chromium智能指针&quot;&gt;&lt;/a&gt;Chromium智能指针&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接下来我们继续分析Chromium实现的第一类智能指针和第二类智能指针，以及弱智能指针。&lt;/p&gt;
&lt;h2 id=&quot;第一类智能指针-1&quot;&gt;&lt;a href=&quot;#第一类智能指针-1&quot; class=&quot;headerlink&quot; title=&quot;第一类智能指针&quot;&gt;&lt;/a&gt;第一类智能指针&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Chromium的第一类智能指针由类scoped_refptr实现。由于它要求被引用对象具有计数功能，因此就提供了一个具有计数功能的基类RefCounted。当一个对象可以被类scoped_refptr描述的对象引用时，它就必须要从基类RefCounted继承下来。这一点与WebKit的第一类智能指针RefPtr是类似的。&lt;/p&gt;
&lt;p&gt;Chromium的RefCounted类的实现如下所示，这个类定义在文件external/chromium_org/base/memory/ref_counted.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; T&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; RefCounted : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; subtle::RefCountedBase &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  RefCounted() &amp;#123;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;AddRef&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    subtle::RefCountedBase::AddRef();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Release&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (subtle::RefCountedBase::Release()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      &lt;span class=&quot;keyword&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; T*&amp;gt;(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Chromium的RefCounted类定义了两个成员函数AddRef和Release，分别用来增加和减少目标对象的1个引用计数，并且都是通过调用父类RefCountedBase的成员函数AddRef和Release来实现的。当减少目标对象的1引用计数之后，如果目标对象的引用计数变为0，那么目标对象就会被delete掉。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Chromium的RefCountedBase类的定义如下所示，这个类定义在文件external/chromium_org/base/memory/ref_counted.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; BASE_EXPORT RefCountedBase &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  RefCountedBase()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      : ref_count_(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;AddRef&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ++ref_count_;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Release&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (--ref_count_ == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;mutable&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; ref_count_;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Chromium的RefCountedBase类与WebKit的RefCountedBase类也是几乎一样，都是提供了非线程安全版本的计数功能。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Chromium提供的线程安全版本的具有计数功能的基类是RefCountedThreadSafe，它的实现如下所示，这个类定义在文件external/chromium_org/base/memory/ref_counted.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; T, &lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; Traits = DefaultRefCountedThreadSafeTraits&amp;lt;T&amp;gt; &amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; RefCountedThreadSafe : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; subtle::RefCountedThreadSafeBase &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; AddRef() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    subtle::RefCountedThreadSafeBase::AddRef();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Release&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (subtle::RefCountedThreadSafeBase::Release()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      Traits::Destruct(&lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; T*&amp;gt;(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;friend&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; DefaultRefCountedThreadSafeTraits&amp;lt;T&amp;gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;DeleteInternal&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; T* x)&lt;/span&gt; &lt;/span&gt;&amp;#123; &lt;span class=&quot;keyword&quot;&gt;delete&lt;/span&gt; x; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Chromium的RefCountedThreadSafe类与RefCountedBase类的实现也类似，不过有两点区别：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;RefCountedThreadSafe类是从RefCountedThreadSafeBase类继承下来的，后者提供了线程安全版本的计数功能。&lt;/li&gt;
&lt;li&gt;RefCountedThreadSafe类可以通过模板参数Traits指定一个类，当它引用的目标对象的引用计数等于0的时候，就会调用该参数Traits指定的类的静态成员函数Destruct来释放目标对象。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;第2点是很有用的。比如我们在一个线程创建一个T对象，这个T对象可能会被其它线程引用。当这个T对象的引用计数是在其它线程减少为0时，我们希望它不要在其它线程释放，而是要在创建线程进行释放，那么就可以通过指定参数Traits来实现。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果没有指定模板参数Traits，那么它的默认值就为DefaultRefCountedThreadSafeTraits。这个DefaultRefCountedThreadSafeTraits类的实现如下所示，这个类定义在文件external/chromium_org/base/memory/ref_counted.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; DefaultRefCountedThreadSafeTraits &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Destruct&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; T* x)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    RefCountedThreadSafe&amp;lt;T,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                         DefaultRefCountedThreadSafeTraits&amp;gt;::DeleteInternal(x);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;DefaultRefCountedThreadSafeTraits类的静态成员函数Destruct又是通过调用RefCountedThreadSafe类的静态成函数DeleteInternal来释放目标对象的。从RefCountedThreadSafe类的实现可以知道，它的静态成员函数DeleteInternal是直接将目标对象delete掉。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们再来看RefCountedThreadSafe类的父类RefCountedThreadSafeBase的实现，如下所示，这个类定义在文件external/chromium_org/base/memory/ref_counted.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; BASE_EXPORT RefCountedThreadSafeBase &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;AddRef&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;// Returns true if the object should self-delete.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Release&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;mutable&lt;/span&gt; AtomicRefCount ref_count_;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;RefCountedThreadSafeBase类提供了两个成员函数AddRef和Release，用来执行线程安全的引用计数加1和减1操作，它们的实现如下所示，这两个函数定义在文件external/chromium_org/base/memory/ref_counted.cc中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; RefCountedThreadSafeBase::AddRef() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  AtomicRefCountInc(&amp;amp;ref_count_);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; RefCountedThreadSafeBase::Release() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!AtomicRefCountDec(&amp;amp;ref_count_)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;RefCountedThreadSafeBase类的成员函数AddRef和Release分别通过函数AtomicRefCountInc和AtomicRefCountDec对目标对象的引用计数执行原子性的加1和减1操作，因此它们是线程安全的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;有了RefCounted和ThreadSafeRefCounted这两个基类为对象提供计数功能之后，我们就继续分析Chromium的第一类智能指针scoped_refptr的实现，如下所示，这个类定义在文件external/chromium_org/base/memory/ref_counted.h中。：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; T&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; scoped_refptr &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; T element_type;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  scoped_refptr() : ptr_(&lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  scoped_refptr(T* p) : ptr_(p) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ptr_)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      ptr_-&amp;gt;AddRef();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  scoped_refptr(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; scoped_refptr&amp;lt;T&amp;gt;&amp;amp; r) : ptr_(r.ptr_) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ptr_)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      ptr_-&amp;gt;AddRef();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; U&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  scoped_refptr(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; scoped_refptr&amp;lt;U&amp;gt;&amp;amp; r) : ptr_(r.get()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ptr_)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      ptr_-&amp;gt;AddRef();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ~scoped_refptr() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ptr_)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      ptr_-&amp;gt;Release();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;function&quot;&gt;T* &lt;span class=&quot;title&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;/span&gt;&amp;#123; &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; ptr_; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;// Allow scoped_refptr&amp;lt;C&amp;gt; to be used in boolean expression&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;// and comparison operations.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt; T*() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123; &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; ptr_; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  T* &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt;-&amp;gt;() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    assert(ptr_ != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; ptr_;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  scoped_refptr&amp;lt;T&amp;gt;&amp;amp; &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt;=(T* p) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// AddRef first so that self assignment should work&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (p)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      p-&amp;gt;AddRef();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    T* old_ptr = ptr_;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ptr_ = p;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (old_ptr)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      old_ptr-&amp;gt;Release();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; *&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  T* ptr_;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Chromium的scoped_refptr类的实现与WebKit的RefPtr类的实现几乎是一样的，并且都是要求目标对象是从RefCounted类或者ThreadSafeRefCounted类继承下来的，因此我们就不再详述。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;为了方便创建scoped_refptr智能指针，Chromium提供了一个帮助函数make_scoped_refptr，这个函数定义在文件external/chromium_org/base/memory/ref_counted.h中，它的实现如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;scoped_refptr&amp;lt;T&amp;gt; make_scoped_refptr(T* t) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; scoped_refptr&amp;lt;T&amp;gt;(t);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数make_scoped_refptr调用scoped_refptr类的构造函数直接将参数t封装成一个scoped_refptr智能指针，然后返回给调用者。&lt;/p&gt;
&lt;h2 id=&quot;第二类智能指针-1&quot;&gt;&lt;a href=&quot;#第二类智能指针-1&quot; class=&quot;headerlink&quot; title=&quot;第二类智能指针&quot;&gt;&lt;/a&gt;第二类智能指针&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接下来我们再看Chromium的第二类智能指针的实现，它由类scoped_ptr实现，这个类定义在文件external/chromium_org/base/memory/scoped_ptr.h中，如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;template &amp;lt;class T, class D = base::DefaultDeleter&amp;lt;T&amp;gt; &amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;class scoped_ptr &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  COMPILE_ASSERT(base::internal::IsNotRefCounted&amp;lt;T&amp;gt;::value,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                 T_is_refcounted_type_and_needs_scoped_refptr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; public:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  // The element and deleter types.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  typedef T element_type;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  typedef D deleter_type;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  // Constructor.  Defaults to initializing with NULL.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  scoped_ptr() : impl_(NULL) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  // Constructor.  Takes ownership of p.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  explicit scoped_ptr(element_type* p) : impl_(p) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  // Constructor.  Allows initialization of a stateful deleter.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  scoped_ptr(element_type* p, const D&amp;amp; d) : impl_(p, d) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  // Constructor.  Move constructor for C++03 move emulation of this type.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  scoped_ptr(RValue rvalue) : impl_(&amp;amp;rvalue.object-&amp;gt;impl_) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  // Accessors to get the owned object.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  // operator* and operator-&amp;gt; will assert() if there is no current object.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  element_type&amp;amp; operator*() const &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    return *impl_.get();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  element_type* operator-&amp;gt;() const  &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    return impl_.get();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  element_type* get() const &amp;#123; return impl_.get(); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  template &amp;lt;typename PassAsType&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  scoped_ptr&amp;lt;PassAsType&amp;gt; PassAs() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    return scoped_ptr&amp;lt;PassAsType&amp;gt;(Pass());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; private:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  base::internal::scoped_ptr_impl&amp;lt;element_type, deleter_type&amp;gt; impl_;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Chromium的scoped_ptr类与WebKit的OwnPtr类的实现也是类似的：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;通过宏COMPILE_ASSERT以及IsNotRefCounted&lt;t&gt;类的静态成员变量value禁止scoped_ptr智能指针引用的目标对象从RefCounted类或者ThreadSafeRefCounted类继承下来，&lt;strong&gt;也就是不要求目标对象具有引用计数功能&lt;/strong&gt;。&lt;/t&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;通过宏MOVE_ONLY_TYPE_FOR_CPP_03禁止scoped_ptr智能指针的copy语意，但是提供move语意&lt;/strong&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;不同的地方在于：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;可以直接根据目标对象创建scoped_ptr智能指针。WebKit要先根据目标对象创建PassOwnPtr智能指针，再根据PassOwnPtr智能指针创建OwnPtr智能指针。&lt;/li&gt;
&lt;li&gt;Chromium不像WebKit一样，单独提供了一个可以用来传递目标对象的PassOwnPtr智能指针，而是直接在scoped_ptr智能指针中集成了该功能，也就是通过scoped_ptr类的成员函数PassAs来实现。&lt;/li&gt;
&lt;li&gt;scoped&lt;em&gt;ptr类将引用的目标对象间接保存在成员变量impl&lt;/em&gt;描述的一个scoped_ptr_impl对象中。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;类scoped_ptr_impl的实现如下所示， 这个类定义在文件external/chromium_org/base/memory/scoped_ptr.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;class scoped_ptr_impl &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; public:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  explicit scoped_ptr_impl(T* p) : data_(p) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  // Initializer for deleters that have data parameters.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  scoped_ptr_impl(T* p, const D&amp;amp; d) : data_(p, d) &amp;#123;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  template &amp;lt;typename U typename V&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  scoped_ptr_impl(scoped_ptr_impl&amp;lt;U, V&amp;gt;* other)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      : data_(other-&amp;gt;release(), other-&amp;gt;get_deleter()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ~scoped_ptr_impl() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (data_.ptr != NULL) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      static_cast&amp;lt;D&amp;amp;&amp;gt;(data_)(data_.ptr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  T* get() const &amp;#123; return data_.ptr; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  T* release() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    T* old_ptr = data_.ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    data_.ptr = NULL;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    return old_ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; private:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  struct Data : public D &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    explicit Data(T* ptr_in) : ptr(ptr_in) &amp;#123;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Data(T* ptr_in, const D&amp;amp; other) : D(other), ptr(ptr_in) &amp;#123;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    T* ptr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  Data data_;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;类scoped_ptr&lt;em&gt;impl将目标对象保存在成员变量data&lt;/em&gt;描述的一个Data对象的成员变量ptr中。同时，我们可以通过模板参数D指定一个类，当scoped_ptr_impl智能指针超出其生命周期范围时，目标对象通过调用该类的操作符重载函数operator()来释放。这一点与scoped_refptr智能指针的实现是类似的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;此外，类scoped_ptr_impl还提供了一个release成员函数和一个拷贝构造函数，前者用来释放对目标对象的引用，后者却不是直接将参数描述的scoped_ptr_impl对象拷贝到当前正在构造的scoped_ptr_impl对象，而是将参数描述的scoped_ptr_impl对象引用的目标对象转移给当前构造的scoped_ptr_impl对象，因此这个构造函数实现的实际上是一个move语意的构造函数，而不是一个copy语意的构造函数。&lt;/p&gt;
&lt;h2 id=&quot;Move语意-1&quot;&gt;&lt;a href=&quot;#Move语意-1&quot; class=&quot;headerlink&quot; title=&quot;Move语意&quot;&gt;&lt;/a&gt;Move语意&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接下来，我们继续分析scoped_ptr智能指针是如何通过宏MOVE_ONLY_TYPE_FOR_CPP_03来禁止copy语意和实现move语意义的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;宏MOVE_ONLY_TYPE_FOR_CPP_03的定义如下所示，这个宏定义在文件external/chromium_org/base/move.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;define&lt;/span&gt; MOVE_ONLY_TYPE_FOR_CPP_03(type, rvalue_type) \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; private: \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  struct rvalue_type &amp;#123; \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    explicit rvalue_type(type* object) : object(object) &amp;#123;&amp;#125; \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    type* object; \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;; \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  type(type&amp;amp;); \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  void operator=(type&amp;amp;); \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; public: \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  operator rvalue_type() &amp;#123; return rvalue_type(this); &amp;#125; \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  type Pass() &amp;#123; return type(rvalue_type(this)); &amp;#125; \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  typedef void MoveOnlyTypeForCPP03; \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; private:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;因此，scoped_ptr类内部的宏MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)展开后就得到：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;private:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  struct RValue &amp;#123; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    explicit RValue(scoped_ptr* object) : object(object) &amp;#123;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    scoped_ptr* object; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  scoped_ptr(scoped_ptr&amp;amp;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  void operator=(scoped_ptr&amp;amp;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; public:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  operator RValue() &amp;#123; return RValue(this); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  scoped_ptr Pass() &amp;#123; return scoped_ptr(RValue(this)); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  typedef void MoveOnlyTypeForCPP03;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; private:&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这意味着在scoped_ptr类的内部，有一个结构体RValue。这个RValue结构体就是用来实现C++ 11的右值引用的，但是这里不是通过T&amp;amp;&amp;amp;关键字来描述右值引用的。这意味着即使是在不支持C++ 11的编译器中，scoped_ptr也能实现move语意。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;同时，scoped_ptr类的拷贝构造函数和赋值操作符函数被声明为私有的，并且没有相应的实现。这意味着scoped_ptr智能指针不能拷贝给另外一个scoped_ptr智能指针，因为这样会违反一个目标对象在同一时刻被多个第二类智能指针引用的原则。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;此外，scoped_ptr类提供了两个成员函数RValue和Pass。其中，前者用来将一个scoped_ptr智能指针封装成一个RValue结构体，也就是一个右值引用，后者将一个scoped_ptr智能指针引用的目标对象转移给另外一个scoped_ptr智能指针。scoped_ptr类的这两个成员函数以及以const RValue&amp;amp;为参数的构造函数一起实现了scoped_ptr智能指针的move语意。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们通过以下代码片断说明scoped_ptr智能指针的move语意的实现过程，如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;scoped_ptr&amp;lt;T&amp;gt; p1(&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; T());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;scoped_ptr&amp;lt;T&amp;gt; p2 = p1.Pass();&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;首先，scoped_ptr智能指针p1引用了一个目标对象，接着，我们要将scoped_ptr智能指针p1引用的目标对象转移给scoped_ptr智能指针p2。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;调用scoped_ptr智能指针p1的成员函数Pass的时候，发生了以下事情：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;创建了一个RValue临时对象。&lt;/li&gt;
&lt;li&gt;创建了一个scoped_ptr临时对象。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;第2步创建的scoped_ptr临时对象接下来被赋值给scoped_ptr智能指针p2，这时候又会发生以下事情：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;由于scoped_ptr类的拷贝构造函数被声明为私有的，并且没相应的实现，因此，上述创建的scoped_ptr临时对象不能通过scoped_ptr类的拷贝构造函数来构造scoped_ptr智能指针p2，也就是不能通过scoped_ptr类的拷贝构造函数将scoped_ptr智能指针p1引用的目标对象转移给scoped_ptr智能指针p2。&lt;/li&gt;
&lt;li&gt;scoped_ptr类实现了一个以const RValue&amp;amp;为参数的构造函数，因此前面创建的scoped_ptr临时对象首先会被scoped_ptr类的操作符成员函数operator RValue转化为一个临时的RValue对象。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在scoped_ptr类以const RValue&amp;amp;为参数的构造函数的调用过程中又会发生以下事：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;参数rvalue描述的RValue对象的成员变量object描述的scoped_ptr智能指针（也就是scoped&lt;em&gt;ptr智能指针p1）的成员变量impl&lt;/em&gt;将会用来初始化正在构造的智能指针（也就是scoped&lt;em&gt;ptr智能指针p2）的成员变量impl&lt;/em&gt;，也就是会调用前面分析的scoped_ptr_impl类的拷贝构造函数。&lt;/li&gt;
&lt;li&gt;由于scoped_ptr_impl类的拷贝构造函数实现的是move语意的拷贝操作，因此当它执行完成之后，scoped_ptr智能指针p1引用的目标对象将会转移到给scoped_ptr智能指针p2引用，也就是说，scoped_ptr智能指针p1自动放弃了对目标对象的引用。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;因此，通过调用scoped_ptr类的成员函数Pass，就能够将一个scoped_ptr智能指针引用的目标对象转移到另外一个scoped_ptr智能指针，也就是实现了scoped_ptr智能指针的move语意。此外，scoped_ptr类还提供了另外一个成员函数PassAs，它的作用与成员函数Pass是一样的。&lt;/p&gt;
&lt;h2 id=&quot;弱智能指针-1&quot;&gt;&lt;a href=&quot;#弱智能指针-1&quot; class=&quot;headerlink&quot; title=&quot;弱智能指针&quot;&gt;&lt;/a&gt;弱智能指针&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接下来我们再看Chromium的弱智能指针的实现，它由类WeakPtr实现。我们首先给出WeakPtr类的关系图，如图1所示：  &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Chromium%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%EF%BC%88%E4%B8%80%EF%BC%89%E2%80%94%E2%80%94%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86%E5%88%86%E6%9E%90/SmartPointer.jpg&quot; alt=&quot;弱智能指针&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WeakPtr类继承于WeakPtrBase类。WeakPtrBase类有一个成员变量ref_，它指向一个WeakReference对象。WeakPtr类实现弱智能指针的功能的关键点就在于这个WeakReference对象，那么这个WeakReference对象是怎么来的呢？&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;一个对象如果需要被弱智能指针引用，那么它所属的类就必须要继承于SupportsWeakPtr类。SupportsWeakPtr类又是继承于SupportsWeakPtrBase类的。SupportsWeakPtrBase类有一个静态成员函数StaticAsWeakPtr，用来将一个间接继承于SupportsWeakPtr类的子类对象封装成一个WeakPtr弱智能指针。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SupportsWeakPtr类有一个成员函数AsWeakPtr，用来将一个SupportsWeakPtr子类对象封装成一个WeakPtr弱智能指针。在封装的过程中，需要用到成员变量weak_reference&lt;em&gt;owner&lt;/em&gt;指向的一个WeakReferenceeOwner对象。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WeakReferenceeOwner类有一个成员变量flag_，它指向一个Flag对象。这个Flag对象有一个布尔类型的成员变量is&lt;em&gt;valid&lt;/em&gt;。当一个WeakReferenceeOwner对象所属的SupportsWeakPtr对象被销毁时，也就是它的析构函数被调用的时候，这个WeakReferenceeOwner对象的成员函数Invalidate就会被调用。WeakReferenceeOwner类的成员函数Invalidate又会进一步调用成员变量flag_指向的一个Flag对象的成员函数Invalidate，将该Flag对象的成员变量is&lt;em&gt;valid&lt;/em&gt;的值设置为false，表示一个相应的SupportsWeakPtr对象被销毁了。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当我们调用SupportsWeakPtr类的成员函数AsWeakPtr来获得一个WeakPtr弱智能指针时，SupportsWeakPtr类的成员函数AsWeakPtr先会调用成员变量weak_reference&lt;em&gt;owner&lt;/em&gt;指向的一个WeakReferenceeOwner对象的成员函数GetRef创建一个WeakReference对象，这个WeakReference对象通过成员变量flag&lt;em&gt;引用了上述的WeakReferenceeOwner对象的成员变量flag&lt;/em&gt;指向的一个Flag对象。这意味在图1中，WeakReferenceeOwner类和WeakReference对象的成员变量flag_指向的都是同一个Flag对象。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这相当于就是通过一个共同的Flag对象将一个WeakPtr弱智能指针与它所引用的目标对象关联起来，这样我们需要使用一个WeakPtr弱智能指针所引用的目标对象时，就可以通过上述的共同Flag对象的成员函数IsValid来判断目标对象是否已经被销毁，实际上就是判断该Flag对象的成员变量is&lt;em&gt;valid&lt;/em&gt;是否等于true。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;为了更清楚地表达图1所示的WeakPtr类关系图，接下来我们通过代码来分析该类关系图中涉及到的每一个类。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们首先看SupportsWeakPtrBase类的实现，这个类定义在文件external/chromium_org/base/memory/weak_ptr.h中，如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; SupportsWeakPtrBase &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; Derived&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; WeakPtr&amp;lt;Derived&amp;gt; StaticAsWeakPtr(Derived* t) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; AsWeakPtrImpl&amp;lt;Derived&amp;gt;(t, *t);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; Derived, &lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; Base&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; WeakPtr&amp;lt;Derived&amp;gt; AsWeakPtrImpl(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      Derived* t, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; SupportsWeakPtr&amp;lt;Base&amp;gt;&amp;amp;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    WeakPtr&amp;lt;Base&amp;gt; ptr = t-&amp;gt;Base::AsWeakPtr();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; WeakPtr&amp;lt;Derived&amp;gt;(ptr.ref_, &lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;Derived*&amp;gt;(ptr.ptr_));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;前面提到，一个类如果要配合WeakPtr弱智能指针使用，那么该类必须要从SupportsWeakPtr继承下来，如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; Base : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; base::SupportsWeakPtr&amp;lt;Base&amp;gt; &amp;#123;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这时候如果有一个类Derived又继承了Base类，如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; Derived : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; Base &amp;#123;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这时候如果我们有一个Derived对象，并且想创建一个WeakPtr智能指针引用该Derived对象，那么是不能调用从父类Base继承下来的成员函数AsWeakPtr来创建的，如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;Derived derived;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;base::WeakPtr&amp;lt;Derived&amp;gt; ptr = derived.AsWeakPtr();&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这是因为SupportsWeakPtr&amp;lt; Base &amp;gt;类的成员函数AsWeakPtr返回的是一个WeakPtr&amp;lt; Base &amp;gt;对象，并且这个WeakPtr&amp;lt; Base &amp;gt;对象不能自动转换为一个WeakPtr&amp;lt; Derived &amp;gt;对象。‘&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;为了能够实现上述转换，我们要使用到一个AsWeakPtr函数，这个函数定义在文件external/chromium_org/base/memory/weak_ptr.h中，它的实现如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; Derived&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;WeakPtr&amp;lt;Derived&amp;gt; AsWeakPtr(Derived* t) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; internal::SupportsWeakPtrBase::StaticAsWeakPtr&amp;lt;Derived&amp;gt;(t);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;有了这个AsWeakPtr函数之后，就可以通过下面的代码来创建一个WeakPtr&amp;lt; Derived &amp;gt;对象：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;Derived derived;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;base::WeakPtr&amp;lt;Derived&amp;gt; ptr = base::AsWeakPtr(&amp;amp;derived);&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数AsWeakPtr调用了SupportsWeakPtrBase类的静态成员函数StaticAsWeakPtr，后者又通过调用SupportsWeakPtrBase类的静态成员函数AsWeakPtrImpl创建了一个WeakPtr&amp;lt; Derived &amp;gt;对象。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SupportsWeakPtrBase类的静态成员函数AsWeakPtrImpl首先是调用参数t描述的一个Derived对象从父类Base继承下来的成员函数AsWeakPtr来创建一个WeakPtr&amp;lt; Base &amp;gt;对象。每一个WeakPtr&amp;lt; Base &amp;gt;对象都有一个成员变量ptr_，它保存的就是WeakPtr&lt;base&gt;对象所引用的目标对象的地址值。有了目标对象的地址值之后，就可以将它转化一个Derived指针。这里能够转换成功，是因为Derived类是继承于Base类的。有了这个Derived指针之后，再结合前面获得的WeakPtr&lt;base&gt;对象的成员变量ref_r描述的一个WeakReference对象之后，就可以通过模板类WeakPtr&amp;lt; Derived &amp;gt;的构造函数来创建一个WeakPtr&amp;lt; Derived &amp;gt;对象了，也就是创建一个引用了Derived对象的WeakPtr智能指针了。后面我们分析WeakPtr类的实现时，就会更清楚地理解上述过程。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接着我们看SupportsWeakPtr类的实现，这个类定义在文件external/chromium_org/base/memory/weak_ptr.h中，如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; T&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; SupportsWeakPtr : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; internal::SupportsWeakPtrBase &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  WeakPtr&amp;lt;T&amp;gt; AsWeakPtr() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; WeakPtr&amp;lt;T&amp;gt;(weak_reference_owner_.GetRef(), &lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;T*&amp;gt;(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  internal::WeakReferenceOwner weak_reference_owner_;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SupportsWeakPtr类最主要的就是通过成员变量weak_reference&lt;em&gt;owner&lt;/em&gt;引用了一个WeakReferenceOwner对象。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WeakReferenceOwner类的定义如下所示，这个类定义在文件external/chromium_org/base/memory/weak_ptr.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; BASE_EXPORT WeakReferenceOwner &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ~WeakReferenceOwner();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;function&quot;&gt;WeakReference &lt;span class=&quot;title&quot;&gt;GetRef&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Invalidate&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;mutable&lt;/span&gt; scoped_refptr&amp;lt;WeakReference::Flag&amp;gt; flag_;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WeakReferenceOwner类最主要的就是通过成员变量flag_引用了一个Flag对象。注意，这个成员变量通过scoped_refptr智能指针来引用Flag对象。这意味着Flag类是具有引用计数功能的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Flag类的定义如下所示，这个类定义在文件external/chromium_org/base/memory/weak_ptr.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; BASE_EXPORT WeakReference &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; BASE_EXPORT Flag : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; RefCountedThreadSafe&amp;lt;Flag&amp;gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Flag();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Invalidate&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;IsValid&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   &lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; is_valid_;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Flag类继承于RefCountedThreadSafe类，因此它就具有引用计数功能，并且在增加和减少引用计数时是线程安全的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;现在我们分析前面列出的SupportsWeakPtr类的成员函数AsWeakPtr的实现，它首先是调用成员变量weak_reference&lt;em&gt;owner&lt;/em&gt;指向的一个WeakReferenceOwner对象的成员函数GetRef获得一个WeakReference对象，然后再通过WeakPtr类的构造函数创建一个WeakPtr弱智能指针。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WeakReferenceOwner类的成员函数GetRef的实现如下所示，这个函数定义在文件external/chromium_org/base/memory/weak_ptr.cc中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;WeakReference WeakReferenceOwner::GetRef() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;// If we hold the last reference to the Flag then create a new one.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!HasRefs())&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    flag_ = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; WeakReference::Flag();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; WeakReference(flag_.get());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WeakReferenceOwner类的成员函数GetRef首先是调用成员函数HasRefs判断成员变量flag&lt;em&gt;是否指向了一个Flag对象。如果不是，那么就需要创建一个Flag对象，并且保存在成员变量flag&lt;/em&gt;中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WeakReferenceOwner类的成员函数GetRef接下来再以成员变量flag_指向的Flag对象为参数，创建一个WeakReference对象。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WeakReference类的定义如下所示，这个类定义在文件external/chromium_org/base/memory/weak_ptr.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; BASE_EXPORT WeakReference &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;explicit&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;WeakReference&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Flag* flag)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  scoped_refptr&amp;lt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Flag&amp;gt; flag_;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WeakReference类以const Flag*为参数的构造函数的实现如下所示，这个函数定义在文件external/chromium_org/base/memory/weak_ptr.cc中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;WeakReference::WeakReference(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Flag* flag) : flag_(flag) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;它主要就是用参数flag描述的一个Flag对象来初始化成员变量flag_描述的一个scoped_refptr智能指针。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;回到SupportsWeakPtr类的成员函数AsWeakPtr中，得到了一个WeakReference对象之后，就可以创建一个WeakPtr对象了。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WeakPtr类的定义如下所示，这个类定义在文件external/chromium_org/base/memory/weak_ptr.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; T&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; WeakPtr : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; internal::WeakPtrBase &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; U&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  WeakPtr(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; WeakPtr&amp;lt;U&amp;gt;&amp;amp; other) : WeakPtrBase(other), ptr_(other.ptr_) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;function&quot;&gt;T* &lt;span class=&quot;title&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;/span&gt;&amp;#123; &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; ref_.is_valid() ? ptr_ : &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  T&amp;amp; &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt;*() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; *get();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  T* &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt;-&amp;gt;() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; get();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  WeakPtr(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; internal::WeakReference&amp;amp; ref, T* ptr)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      : WeakPtrBase(ref),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ptr_(ptr) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  .....&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  T* ptr_;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从这里就可以看到，WeakPtr类是从WeakPtrBase类继承下来的，后者的定义如下所示，这个类定义在文件external/chromium_org/base/memory/weak_ptr.h中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; BASE_EXPORT WeakPtrBase &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;explicit&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;WeakPtrBase&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; WeakReference&amp;amp; ref)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  WeakReference ref_;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WeakPtrBase类主要就是通过成员变量ref_引用一个WeakReference对象。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当我们调用WeakPtr类的构造函数将一个WeakReference对象和一个目标对象封装成一个WeakPtr对象的时候，WeakPtr类的构造函数会调用父类WeakPtrBase的构造函数将上述WeakReference对象保存在其成员变量ref_中，如下所示，这个函数定义在文件external/chromium_org/base/memory/weak_ptr.cc中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;WeakPtrBase::WeakPtrBase(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; WeakReference&amp;amp; ref) : ref_(ref) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;再回到WeakPtr类以WeakReference对象和T对象指针为参数的构造函数中，它将WeakReference对象保存在父类WeakPtrBase的成员变量ref&lt;em&gt;之后，还会将T对象指针保存在自己的成员变量ptr&lt;/em&gt;中，该成员变量描述的就是一个WeakPtr弱智能指针所引用的目标对象。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里有一点需要注意的是，WeakPtr类的成员变量ptr_指向的T对象有可能是已经被销毁了的，这是因为弱智能指针不能阻止它所引用的对象被销毁。也就是说，当我们在使用一个WeakPtr弱智能指针的时候，它所引用的目标对象有可能是已经被销毁的。我们可以通过WeakPtr类的成员函数get来判断一个WeakPtr弱智能指针所引用的目标对象是否已经被销毁。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WeakPtr类的成员函数get调用从父类WeakPtrBase继承下来的成员变量ref_指向的一个WeakReference对象的成员函数is&lt;em&gt;valid判断一个WeakPtr弱智能指针所引用的目标对象是否已经被销毁。如果还没有被销毁，那么就说明WeakPtr类的成员变量ptr&lt;/em&gt;描述的对象地址是有效的，因此就将它返回调用者。如果已经被销毁，那么就返回一个NULL值给调用者。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WeakReference类的成员函数is_valid的实现如下所示，这个函数定义在文件external/chromium_org/base/memory/weak_ptr.cc中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; WeakReference::is_valid() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123; &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; flag_.get() &amp;amp;&amp;amp; flag_-&amp;gt;IsValid(); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WeakReference类的成员函数is&lt;em&gt;valid首先判断成员变量flag&lt;/em&gt;是否指向了一个Flag对象。如果指向了一个Flag对象，那么就调用它的成员函数IsValid判断它所关联的一个对象是否还存活。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Flag类的成员函数IsValid的实现如下所示，这个函数定义在文件external/chromium_org/base/memory/weak_ptr.cc中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; WeakReference::Flag::IsValid() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; is_valid_;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt; &amp;#160; &amp;#160; &amp;#160; &amp;#160;Flag类的成员函数IsValid直接将成员变量is&lt;em&gt;valid&lt;/em&gt;的值返回给调用者。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从前面分析的WeakReferenceOwner类的成员函数GetRef可以知道，上述的Flag对象即为目标对象通过WeakReferenceOwner类的关联的那个Flag对象，这个Flag对象在创建的时候，它的成员变量is&lt;em&gt;valid&lt;/em&gt;被设置为true，如下所示，这个函数定义在文件external/chromium_org/base/memory/weak_ptr.cc中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;WeakReference::Flag::Flag() : is_valid_(&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当一个Flag对象的宿主WeakReferenceOwner对象被析构时，就会将它的成员变量is&lt;em&gt;valid&lt;/em&gt;的值设置为false，如下所示，这个函数定义在文件external/chromium_org/base/memory/weak_ptr.cc中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;WeakReferenceOwner::~WeakReferenceOwner() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  Invalidate();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WeakReferenceOwner类的析构函数调用了另外一个成员函数Invalidate，它的实现如下所示，这个函数定义在文件external/chromium_org/base/memory/weak_ptr.cc中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; WeakReferenceOwner::Invalidate() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (flag_.get()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    flag_-&amp;gt;Invalidate();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    flag_ = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WeakReferenceOwner类的成员函数Invalidate首先检查成员变量flag_是否指向了一个Flag对象。如果指向了，那么就调用该Flag对象的成员函数Invalidate将它的成员变量is&lt;em&gt;valid&lt;/em&gt;的值设置为false，如下所示，这个函数定义在文件external/chromium_org/base/memory/weak_ptr.cc中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; WeakReference::Flag::Invalidate() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  is_valid_ = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;那么，一个WeakReferenceOwner对象什么时候会被析构呢？前面提到，SupportsWeakPtr类有一个成员变量weak_reference&lt;em&gt;owner&lt;/em&gt;描述的是一个WeakReferenceOwner对象。这意味着当一个SupportsWeakPtr对象被析构时，它的成员变量weak_reference&lt;em&gt;owner&lt;/em&gt;描述的是一个WeakReferenceOwner对象也会随之析构。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SupportsWeakPtr类是作为一个被WeakPtr弱智能指针引用的目标对象的父类的，因此当一个WeakPtr弱智能指针引用的目标对象被析构时，目标对象的父类SupportsWeakPtr有的成员变量weak_reference&lt;em&gt;owner&lt;/em&gt;描述的是一个WeakReferenceOwner对象就会被析构，随后又会将与该WeakReferenceOwner对象关联的Flag对象的成员变量is&lt;em&gt;valid&lt;/em&gt;的值设置为true，最后WeakPtr弱智能指针就可以通过该Flag对象的成员函数IsValid判断出它所引用的目标对象是否已经被销毁，从而就实现它作为弱智能指针的作用。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;以上就是Chromium的弱智能指针的实现原理。与WebKit的弱智能指针的实现原理相比，两者都是通过为目标对象关联一个额外的对象来实现的。这个额外的对象的生命周期比目标对象长，也就是说，即使目标对象不存在，该额外的对象也可以继续存在，直到所有引用了该目标对象的弱智能指针都超出其生命周期范围之后。不过两者也有不同的地方，例如，Chromium的弱智能指针是通过继承方式关联额外的对象的，而WebKit的弱智指针是通过组合方式关联额外的对象的。&lt;/p&gt;
&lt;h1 id=&quot;总结&quot;&gt;&lt;a href=&quot;#总结&quot; class=&quot;headerlink&quot; title=&quot;总结&quot;&gt;&lt;/a&gt;总结&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;至此我们也分析完成了Chromium的智能指针的实现。最后结合&lt;a href=&quot;http://windrunnerlihuan.com/2016/08/23/智能指针简单分析/&quot;&gt;Android系统的智能指针&lt;/a&gt;（轻量级指针、强指针和弱指针）的实现原理分析这篇文章，我们总结一下WebKit、Chromium和Android的智能指针的实现的主要相同点与不同点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;WebKit和Chromium的智能指针分别提供了线程不安全和线程安全两个版本的具有引用计数功能的基类RefCounted和ThreadSafeRefCounted。这样我们在设计一个类的时候，就需要考虑这个类的对象是否会在多线程环境下被访问。如果是的话，那么需要选择ThreadSafeRefCounted作为基类。否则的话，选择RefCounted作为基类就可以了。由于RefCounted在增加和减少引用计数时，不需要执行原子操作，因此效率就会更高。Android的智能指针只提供了线程安全版本的具有引用计数功能的基类RefBase和LightRefBase。其中，继承了RefBase类的子类的对象可以配合强指针和弱指针使用，而继承了LightRefBase类的子类的对象只可以配合轻量级指针使用。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;WebKit和Chromium同时提供了引用计数版本和非引用计数版本的智能指针的实现，即RefPtr和scoped_refptr，以及OwnPtr和scoped_ptr。Android没有提供非引用计数版本的智能指针的实现。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;WebKit优化了智能指针作为函数参数和函数返回值传递目标对象的过程，避免对目标对象的引用计数进行频繁的加1和减1操作，这是通过PassRefPtr类和PassOwnPtr类实现的。Chromium和Android没有提供此类智能指针的实现。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;WebKit和Chromium的智能指针都实现了move语意，但是Android的智能指针没有实现move语意。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Chromium和Android的弱智能指针是通过继承方式关联一个生命周期比目标对象更长的额外对象来实现的，而WebKit的弱智能指针则是通过组合方式关联一个生命周期比目标对象更长的额外对象来实现的。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;WebKit和Chromium在实现一个类的时候，可以选择是否需要同时支持强智能指针和弱智能指针，但是Android在实现一个类的时候，对强智能指针和弱智能指针的支持是整体的，也就是要么同时支持强智能指针和弱智能指针，要么同时不支持强智能指针和弱智能指针。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从上面这6点总结就可以看出，WebKit和Chromium的智能指针设计更加精细化和组件化，开发者在设计一个类的时候，可以根据需要有选择地实现相应的智能指针功能，而Android的智能指针设计相对来说就比较粗略，没有太多可选择的余地。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Chromium%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%EF%BC%88%E4%B8%80%EF%BC%89%E2%80%94%E2%80%94%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86%E5%88%86%E6%9E%90/meizi.png&quot; alt=&quot;妹子图&quot;&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Chromium和WebKit的智能指针实现原理分析。&lt;br&gt;
    
    </summary>
    
      <category term="Chromium" scheme="http://windrunnerlihuan.com/categories/Chromium/"/>
    
    
      <category term="Chromium" scheme="http://windrunnerlihuan.com/tags/Chromium/"/>
    
      <category term="智能指针" scheme="http://windrunnerlihuan.com/tags/%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88/"/>
    
  </entry>
  
  <entry>
    <title>Chromium学习之路-启动篇</title>
    <link href="http://windrunnerlihuan.com/2019/03/19/Chromium%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%90%AF%E5%8A%A8%E7%AF%87/"/>
    <id>http://windrunnerlihuan.com/2019/03/19/Chromium学习之路-启动篇/</id>
    <published>2019-03-19T09:58:11.000Z</published>
    <updated>2019-03-19T19:56:34.961Z</updated>
    
    <content type="html">&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;深思熟虑之后，觉得有必要学一下UI渲染技术和JS引擎技术，为以后的跨平台实现打下坚实的基础。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;本篇是一篇科普，将打开苦逼又刺激的Chromium学习之路。&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;Google-Chrome的历史和指导性原则&quot;&gt;&lt;a href=&quot;#Google-Chrome的历史和指导性原则&quot; class=&quot;headerlink&quot; title=&quot;Google Chrome的历史和指导性原则&quot;&gt;&lt;/a&gt;Google Chrome的历史和指导性原则&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Google Chrome最初是2008年下半年作为Windows平台上的一个beta版本发布的。Google还将自己编写的Chrome在BSD许可下进行了开源——称为Chromium。在很多人看来，这一串事件的发生颇为意外：浏览器战争要再次重启了吗？Google真的能做的更好吗？&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;“它非常优秀让我不得不改变主意……”。埃里克•施密特在谈到他一开始反对开发Google Chrome时这样说道。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;答案是，他们能。时至今日，Chrome已经成为使用最广泛的网络浏览器（根据StatCounter的数据，市场份额超过35%），并且兼容Windows、Linux、OS X、Chrome OS多种操作系统，还包括Android和iOS等移动平台。显然，Chrome的特性和功能很对用户的胃口，其很多创新之举还被其他流行的浏览器所吸收和学习。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;有一本解释Google Chrome的思想和创新的&lt;a href=&quot;https://www.google.com/googlebooks/chrome/med_00.html&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;原版38页漫画书&lt;/a&gt;，它很好地概括了Chrome受欢迎背后的思路和设计过程。但这只是开始。最初推动着Chrome开发的那些核心原则仍然是它持续优化的指导性原则：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;快速：做出&lt;strong&gt;最快&lt;/strong&gt;的浏览器&lt;/li&gt;
&lt;li&gt;安全：为用户提供&lt;strong&gt;最安全&lt;/strong&gt;的环境&lt;/li&gt;
&lt;li&gt;稳定：提供&lt;strong&gt;有弹性且稳定&lt;/strong&gt;的网络应用平台&lt;/li&gt;
&lt;li&gt;简单：技术精妙蕴含在&lt;strong&gt;简单的用户体验中&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;正如开发团队所看到的那样，我们今天所使用的很多网站都不再仅仅是网页，而是应用程序。这些越来越有野心的应用需要速度、安全和稳定。这些方面，每个都值得单独成文来介绍，不过，因为我们的主题是性能，我们将重点介绍性能。&lt;/p&gt;
&lt;h1 id=&quot;性能的多个方面&quot;&gt;&lt;a href=&quot;#性能的多个方面&quot; class=&quot;headerlink&quot; title=&quot;性能的多个方面&quot;&gt;&lt;/a&gt;性能的多个方面&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;现代浏览器是一个平台，就像你的操作系统一样，Google Chrome也遵循这样的设计理念。在Google Chrome之前，所有主流浏览器都是单进程的应用程序。所有打开的页面共享同一地址空间，争夺同一资源。任何页面或浏览器本身出现bug，整体体验都可能被破坏。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;与此相反，Chrome运行于多进程模型，这种模型可以保持进程和内存的隔离性，每个标签页都能拥有一个严密的安全沙盒。随着多核架构的流行，隔绝进程并使各个打开的标签页免受其他出错页面的影响，单是这一点就能证明Chrome在浏览器的竞争中具有显著的性能优势。实际上，我们会发现绝大多数其他浏览器都纷纷效仿Chrome，或者开始转向类似的架构。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;分派进程之后，一个Web程序的执行主要包括三项任务：获取资源，页面布局与呈现，以及执行JavaScript。呈现和脚本执行步骤遵循单线程、交错执行的模型——无法对所得到的DOM（文档对象模型）进行并发式的修改。原因之一是JavaScript本身就是单线程的语言。所以，无论是对于应用程序的开发者还是浏览器的开发者来说，优化呈现和脚本执行运行时的协作方式，是极其重要的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在呈现这一步，Chrome使用的是Blink，这是一种快速、开源、遵守良好标准的布局引擎。在JavaScript这一步，Chrome自带了一个高度优化的V8 JavaScript运行时，它也作为单独开源项目发布，并已经被其他很多流行的项目所吸纳，例如Node.js的运行时。但是如果浏览器的网络连接是阻塞的（等待资源到来），那么优化V8 JavaScript执行或者Blink解析和呈现管道都不会有太大作用。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;浏览器优化各项网络资源的次序、优先级和延迟的能力对整体用户体验是最关键的影响因素。你可能没有注意到，毫不夸张地说，Chrome的网络栈每天都会变得更加聪明，尝试着隐藏或减少各项资源的延迟开销：它会学习可能出现的DNS查询，会记住网络的拓扑结构，会预连接可能的目标站点，等等。从外部看来，它展示出的是一种简单的资源获取机制，但是从内部看来则是对如何优化网络性能并带给用户最佳体验的一次详细而精彩的案例学习。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;让我们进入正题吧。&lt;/p&gt;
&lt;h1 id=&quot;什么是现代Web应用？&quot;&gt;&lt;a href=&quot;#什么是现代Web应用？&quot; class=&quot;headerlink&quot; title=&quot;什么是现代Web应用？&quot;&gt;&lt;/a&gt;什么是现代Web应用？&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在我们接触如何优化网络交互的具体细节之前，先来了解我们所面对的这个问题的发展趋势和背景。换句话说就是，“现代网页或者应用是什么样的？”&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;a href=&quot;https://httparchive.org&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;HTTP Archive&lt;/a&gt;目记录了网络的构造过程，可以帮助我们回答这个问题。这个项目并不是为了爬取网页内容，而是周期性地爬取访问量最大的站点，记录和加总各个站点所用资源数量、内容类型、标头和其他元数据的分析数据。2013年1月的数据，可能会令你吃惊。访问量最大前30万个网络站点来看，一个页面平均：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;为1280KB大小&lt;/li&gt;
&lt;li&gt;由88个资源组成&lt;/li&gt;
&lt;li&gt;连接15个以上不同的主机&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;好好琢磨一下。大小平均超过1MB，包含88个如图片、JavaScript、CSS这样的资源，从15个不同的自有和第三方主机传送出来。而且，这些数字在过去几年还在&lt;a href=&quot;https://httparchive.org/reports/state-of-the-web&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;持续增长&lt;/a&gt;，丝毫没有减缓的迹象。这说明，我们所开发的网络应用正变得越来越大，越来越有野心。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;根据HTTP Archive的数据，做个简单的算术，我们可知每个资源平均大小为15KB（1280KB/88项资源），这意味着浏览器中大多数的网络传输是短小但突发的。这就造成了一些问题，因为基础传输（TCP）是针对大型、流式下载进行优化的。让我们深入地看一看这些网络请求。&lt;/p&gt;
&lt;h1 id=&quot;线上资源请求的生命周期&quot;&gt;&lt;a href=&quot;#线上资源请求的生命周期&quot; class=&quot;headerlink&quot; title=&quot;线上资源请求的生命周期&quot;&gt;&lt;/a&gt;线上资源请求的生命周期&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;W3C的&lt;a href=&quot;https://www.w3.org/TR/navigation-timing/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;浏览时序规范&lt;/a&gt;（Navigation Timing specification）提供了一个浏览器API，让我们可以看到浏览器中每项请求的生命周期背后的时序和性能数据。让我们看看这些组成部分，每一块都是影响最佳用户体验的关键点：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Chromium%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%90%AF%E5%8A%A8%E7%AF%87/browserapi.jpg&quot; alt=&quot;浏览时序图&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;对于一个网络资源的URL，浏览器首先会检查其本地缓存和应用程序缓存。如果你此前获取过该资源，并且提供了适当的&lt;a href=&quot;https://developers.google.com/speed/docs/insights/LeverageBrowserCaching&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;缓存标头&lt;/a&gt;（&lt;code&gt;Expires, Cache-Control&lt;/code&gt;等），则我们可能被允许使用本地副本来响应原请求——最快的请求就是不请求。或者，如果我们需要重新校验该资源（如果资源已过期），或是我们根本从未获取过该资源，那么就必须发起一个高开销的网络请求。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;有了主机名称和资源路径，Chrome首先检查现有的已开启连接中是否有可以重用的——socket按照{&lt;code&gt;scheme, host, port&lt;/code&gt;}的格式储存在池中。或者，如果你已经配置了&lt;a href=&quot;https://en.wikipedia.org/wiki/Proxy_auto-config&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;代理&lt;/a&gt;，或指定了代理自动配置脚本（PAC），那么Chrome就会通过适当的代理来检查连接。PAC脚本允许基于URL的不同代理或其他指定规则，它们都可以有自己的socket池。最后，如果上述条件都不满足，则请求必须通过将主机名解析为IP地址的方式发起，也称为DNS查询。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果幸运的话，主机名可能已经在缓存当中了，此时通常只需要一次快速的系统调用就得到响应。如若不然，就必须调度一个DNS查询才能继续下去。DNS查询耗费的时间由网络提供商、站点的热门程度、主机名可能存在过渡缓存中的概率以及该域名的权威服务器的响应时间所决定。换句话说，影响变量有很多，但是耗费数百毫秒来进行一次DNS查询也并非罕见。天啊。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Chromium%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%90%AF%E5%8A%A8%E7%AF%87/handshake.jpg&quot; alt=&quot;三次握手&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;得到了解析后的IP地址，Chrome现在可以打开一个新的与目标站点的TCP连接，这意味着我们需要进行“三次握手”：&lt;code&gt;SYN &amp;gt; SYN-ACK &amp;gt; ACK&lt;/code&gt;。这一交换过程又为每个新的TCP连接增加了一个往返延迟——此处没有捷径可走。根据客户端与服务器的距离和所选定的路由路径不同，这可能产生几十、几百甚至几千毫秒的延迟。这些工作和延迟是甚至还没有一个字节的应用程序数据开始传输之前就发生的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;完成了TCP握手之后，如果我们连接的是安全站点（HTTPS），那么还要进行SSL握手。这又增加了客户端和服务器之间两个往返延迟。如果SSL会话进行了缓存，那么可以“免去”其中一次额外的往返延迟。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;最后，Chrome要调度HTTP请求（上图中&lt;code&gt;requestStart&lt;/code&gt;）。服务器接收到请求之后，会处理该请求，然后通过数据流把响应数据返给客户端。这至少会产生一个往返延迟，还要算上服务器的处理时间。正常情况下这样就结束了，但如果真正的响应是一个HTTP重定向，那么我们可能还需要把整个过程再重走一遍。你的页面上有不必要的重定向吗？那你可能需要重新考虑这个决定了。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;你算过这所有的延迟时间了吗？为了便于说明问题，我们假设一个典型的宽带连接的最坏情况：没有本地缓存、相对较快的DNS查询速度（50ms）、TCP握手、SSL协商、相对较快的服务器响应时间（100ms）、80ms的往返延迟（这是美国大陆往返延迟的平均时间）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DNS需要50ms&lt;/li&gt;
&lt;li&gt;TCP握手需要80ms（一次往返延迟）&lt;/li&gt;
&lt;li&gt;SSL握手需要160ms（两次往返延迟）&lt;/li&gt;
&lt;li&gt;请求传输到服务器需要40ms&lt;/li&gt;
&lt;li&gt;服务器处理需要100ms&lt;/li&gt;
&lt;li&gt;服务器返回响应需要40ms&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这样算下来，单次请求需要470毫秒，与服务器真正处理请求的时间相比，其中80%都是网络延迟开销。实际上，470毫秒都算是一个乐观的估计了：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果服务器响应不匹配初始的TCP拥塞窗口（4-15KB），还会额外产生一个或多个往返延迟。【注1】&lt;/li&gt;
&lt;li&gt;如果我们需要获取缺失证书或者需要执行在线证书状态检查（OCSP），SSL延迟得还会更厉害，因为这两种情况都需要一次全新的TCP连接，这又增加了成百上千毫秒的额外延迟。&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;“足够快”有多快？&quot;&gt;&lt;a href=&quot;#“足够快”有多快？&quot; class=&quot;headerlink&quot; title=&quot;“足够快”有多快？&quot;&gt;&lt;/a&gt;“足够快”有多快？&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;DNS、握手、往返延迟的网络开销是决定前例中总时间的因素——服务器响应时间仅占总延迟的20%。但是，从大局看，这些延迟重要吗？如果你正在阅读本文，你很可能已经知道了答案：不但有影响，而且影响很大。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;过去一些&lt;a href=&quot;https://www.nngroup.com/articles/response-times-3-important-limits/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;用户体验的研究&lt;/a&gt;描述了我们作为用户对应用程序（在线或离线）的响应速度作何预期：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Delay&lt;/th&gt;
&lt;th&gt;User Reaction&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0 - 100 ms&lt;/td&gt;
&lt;td&gt;Instant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100 - 300 ms&lt;/td&gt;
&lt;td&gt;Small perceptible delay&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100 - 300 ms&lt;/td&gt;
&lt;td&gt;Small perceptible delay&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;300 - 1000 ms&lt;/td&gt;
&lt;td&gt;Machine is working&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1 s+&lt;/td&gt;
&lt;td&gt;Mental context switch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10 s+&lt;/td&gt;
&lt;td&gt;I’ll come back later…&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上表还能够解释网络性能领域中一条不成文的经验法则：如果不能直接呈现页面，至少也要在250毫秒以内提供视觉上的反馈以保持用户不会失去兴趣。其他因素也会影响速度。对Google、Amazon、Microsoft和数千个其他站点的研究显示，额外的延迟会直接影响站点的获利能力：速度快的网站能生成更多的页面请求，用户参与度也更高，从而转化率也更高。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以，我们知道了，最佳的延迟应该控制在250毫秒，但我们在前例中看到，DNS查询、TCP和SSL握手再加上请求传递的时间总共有370毫秒。我们已经超出50%了，这还是我们没算上服务器处理时间的情况！&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以，我们知道了，最佳的延迟应该控制在250毫秒，但我们在前例中看到，DNS查询、TCP和SSL握手再加上请求传递的时间总共有370毫秒。我们已经超出50%了，这还是我们没算上服务器处理时间的情况！&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;对于大多数用户乃至一些网络开发者来说，DNS、TCP和SSL的延迟是完全透明的（无须关心的），它们是在网络层协商的，而我们极少深入到甚至不会去想这个层面的事。但是，这其中的每一步对整体用户体验都是非常关键的，因为每增加额外的网络请求都会增加几十或几百毫秒的延迟。这就是为什么Chrome的网络栈要比一个简单的socket处理器复杂的多得多。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;找到了症结所在，我们继续来看一些实现细节。&lt;/p&gt;
&lt;h1 id=&quot;Chrome的网络栈概览&quot;&gt;&lt;a href=&quot;#Chrome的网络栈概览&quot; class=&quot;headerlink&quot; title=&quot;Chrome的网络栈概览&quot;&gt;&lt;/a&gt;Chrome的网络栈概览&lt;/h1&gt;&lt;h2 id=&quot;多进程架构&quot;&gt;&lt;a href=&quot;#多进程架构&quot; class=&quot;headerlink&quot; title=&quot;多进程架构&quot;&gt;&lt;/a&gt;多进程架构&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Chrome的多进程架构对各个网络请求如何在浏览器中进行处理具有重大影响。在底层，Chrome实际上支持&lt;a href=&quot;http://www.chromium.org/developers/design-documents/process-models&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;四种不同的执行模型&lt;/a&gt;用于确定如何进行进程的分配。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;默认情况下，桌面上的Chrome浏览器使用“站点对应进程”模型，将不同站点隔离开来，而把同一站点的所有实例分组在同一进程中。不过为了简便起见，我们假设最简单的情况：每个打开的标签页对应一个单独的进程。从网络性能的角度看，这种差别并不重要，但“标签页对应进程”模型要容易理解得多。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Chromium%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%90%AF%E5%8A%A8%E7%AF%87/multiprocess.jpg&quot; alt=&quot;多进程架构&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个架构为每个标签页配给一个专用的呈现进程。每个呈现进程包含Blink布局引擎和V8 JavaScript引擎，配合上一些胶水代码把这几个部分（再加上其他一些部分）联系起来。【注2】&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这些呈现进程的每一个都在一个沙盒环境内执行，这个环境对用户计算机——包括网络，只有有限的访问权限。要获得访问这些资源的权限，每个呈现进程要与主浏览器进程（或称为内核进程）进行通信，由内核进程负责管理每个呈现器的安全和权限策略。&lt;/p&gt;
&lt;h2 id=&quot;进程间通信和多进程资源加载&quot;&gt;&lt;a href=&quot;#进程间通信和多进程资源加载&quot; class=&quot;headerlink&quot; title=&quot;进程间通信和多进程资源加载&quot;&gt;&lt;/a&gt;进程间通信和多进程资源加载&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Chrome中呈现器和内核进程之间的所有通信都是通过进程间通信（IPC）完成的。在Linux和OS X上使用的是&lt;code&gt;socketpair&lt;/code&gt;，这个方法提供一个命名的管道传输进行异步通信。来自呈现器的每条消息经过序列化处理再传给专用的I/O线程，再由它将其派发给主浏览器进程。在接收端，内核进程提供一个过滤接口，允许Chrome拦截应该由网络栈处理的资源IPC请求（参见&lt;a href=&quot;https://bugs.chromium.org/p/chromium/adminIntro?q=resourcemessagefilter&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;ResourceMessageFilter&lt;/a&gt;）。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Chromium%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%90%AF%E5%8A%A8%E7%AF%87/processcomm.jpg&quot; alt=&quot;进程间通信&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这种架构的一个优点是，所有的资源请求都完全在I/O线程上处理，用户接口产生的活动与网络事件之间互不干扰。资源过滤器运行在浏览器进程中的I/O线程中，截获资源请求消息，并将其转发给浏览器进程中的ResourceDispatcherHost【注3】单例。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个单例接口允许浏览器控制各个呈现器的网络访问权限，它还能实现高效和一致性的资源共享。一些例子包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;socket池和连接限制：浏览器能够对每个profile、代理和&lt;code&gt;{scheme, host, port}&lt;/code&gt;组所对应的已开启socket数量进行限制（分别为256、32和6个）。注意，按照这个规则，同一&lt;code&gt;{host, port}&lt;/code&gt;最多可以进行6个HTTP和6个HTTPS连接。&lt;/li&gt;
&lt;li&gt;socket重用：持久性的TCP连接会在请求处理之后在socket池中保留一段时间，以供连接重用，这样能够避免发起新的连接额外带来的DNS、TCP和SSL（如有需要）的启动开销。&lt;/li&gt;
&lt;li&gt;socket后期绑定：当socket准备好分派应用程序请求时，请求才与基础的TCP连接绑定起来，这样一来可以获得更好的请求次序优化（例如：当socket在连接中时，更高优先级的请求到达），更大的流量（例如：在现有socket可用而新连接正在打开时，重用“刚使用过”的TCP连接）以及TCP预连接的通用机制和其他一些优化。&lt;/li&gt;
&lt;li&gt;一致的会话状态：所有呈现进程的身份鉴证、cookies和缓存数据都是共享的。&lt;/li&gt;
&lt;li&gt;全局性资源和网络优化：浏览器可以从所有呈现进程和未完成请求的全局做出决策。例如，对前景标签页发起的请求赋予网络优先级。&lt;/li&gt;
&lt;li&gt;预测性优化：通过观测所有的网络流量情况，Chrome能够构建和修正预测性模型提升性能。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;就呈现进程而言，它只是通过IPC发送资源请求消息，这个请求被打上对应浏览器进程的唯一请求ID，剩下的部分都是由浏览器内核进程处理的。&lt;/p&gt;
&lt;h2 id=&quot;跨平台资源获取&quot;&gt;&lt;a href=&quot;#跨平台资源获取&quot; class=&quot;headerlink&quot; title=&quot;跨平台资源获取&quot;&gt;&lt;/a&gt;跨平台资源获取&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;跨Linux、Windows、OS X、Chrome OS、Android和iOS等不同平台的可移植性是Chrome网络栈实现中的一个重要问题。要解决这个挑战性的问题，网络栈被实现为一个几乎单线程（有单独的缓存和代理线程）的跨平台库，使Chrome可以重用相同的基础设施并提供相同的性能优化水平，更有机会进行跨平台的优化。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当然，所有的代码都是开源的，可以在&lt;code&gt;src/net&lt;/code&gt;&lt;a href=&quot;https://cs.chromium.org/#chromium/src/net/&amp;amp;ct=rc&amp;amp;cd=1&amp;amp;q=src.net&amp;amp;sq=package:chromium&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;子目录&lt;/a&gt;中找到。我们不打算详细剖析每个部分，但是代码格局本身就带有很大的信息量，告诉我们它的功能和结构。下表中是一些例子。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;组件&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;net/android&lt;/td&gt;
&lt;td&gt;对Android运行时的绑定。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;net/base&lt;/td&gt;
&lt;td&gt;常用网络工具，如主机解析、cookies、网络变化检测和SSL证书管理。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;net/disk_cache&lt;/td&gt;
&lt;td&gt;实现网络资源的磁盘和内存缓存。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;net/dns&lt;/td&gt;
&lt;td&gt;实现异步DNS解析器。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;net/http&lt;/td&gt;
&lt;td&gt;实现HTTP协议。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;net/proxy&lt;/td&gt;
&lt;td&gt;代理（SOCKS和HTTP）配置、解析和脚本获取等。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;net/socket&lt;/td&gt;
&lt;td&gt;TCP socket、SSL流和socket池的跨平台实现。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;net/spdy&lt;/td&gt;
&lt;td&gt;实现SPDY协议。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;net/url_request&lt;/td&gt;
&lt;td&gt;实现URLRequest、URLRequestContext和URLRequestJob。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;net/websockets&lt;/td&gt;
&lt;td&gt;实现WebSockets协议。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这些组件的代码都让人忍不住想好好读一读，它们文档完备，每个组件你都能找到很多的单元测试。&lt;/p&gt;
&lt;h2 id=&quot;移动平台的架构和性能&quot;&gt;&lt;a href=&quot;#移动平台的架构和性能&quot; class=&quot;headerlink&quot; title=&quot;移动平台的架构和性能&quot;&gt;&lt;/a&gt;移动平台的架构和性能&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;移动端浏览器的使用正在以指数级增长，即使按照保守预测，它也会在不远的将来完全取代桌面浏览。所以不言而喻，提供优化的移动端访问体验一直是Chrome团队的首要任务之一。在2012年初，&lt;a href=&quot;https://www.google.com/intl/en/chrome/browser/mobile/android.html&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Chrome for Android&lt;/a&gt;发布，数月后&lt;a href=&quot;https://www.google.com/intl/en/chrome/browser/mobile/ios.html&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Chrome for iOS&lt;/a&gt;发布。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;于Chrome的移动端版本，第一件需要注意的事是，它并不是简单地直接在桌面浏览器基础上做一些调整——那样并不能得到最好的用户体验。从本质讲，移动端环境的资源更加局限，而且有很多根本不同的操作参数：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;桌面用户通过鼠标来浏览，可以进行窗口重叠，屏幕更大，几乎没有电量的约束，网络连接通常更稳定，能够访问更大的存储和内存池。&lt;/li&gt;
&lt;li&gt;移动端用户使用触摸和手势浏览，屏幕更小，受制于电池和电量的约束，往往使用流量计量的网络，本地存储和内存也较为有限。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;此外，并不存在一个“典型移动设备”。不同硬件能力的各种设备五花八门，要提供最佳性能，Chrome必须适应每种设备的操作约束条件。所幸，Chrome有多种执行模型正好可以实现这一点。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在Android设备上，Chrome沿用了桌面版本中相同的多进程架构——即一个浏览器进程多个呈现进程。一个区别是，由于移动设备的内存有限，Chrome可能不能为每个开启的标签页运行专用的呈现器。Chrome是根据可用内存和设备的其他约束条件确定一个最优的呈现进程数量，由多个标签页共享呈现进程。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当只有最少资源可用时，或者Chrome无法运行多进程时，它也可以切换回使用单进程、多线程处理模型。实际上，在iOS设备上，由于基础平台对沙盒的限制，它就是这样实现的——运行多线程的单一进程。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;网络性能方面呢？首先，Chrome在Android和iOS上使用和其他版本相同的网络栈。这样保证所有平台都有相同的网络优化，Chrome由此获得显著的性能优势。但是，如推测优化技术、socket超时设定与管理逻辑、缓存大小等这样的变量，是有所不同的并且会根据设备功能和所用网络时时调整。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;例如，为了节约电池电量，移动端Chrome可能选择使用闲置socket的懒惰关闭方式——即仅当开启新socket时才关闭旧的，这样来尽可能减少使用广播模组。同样地，因为预呈现（见下文）可能需要大量的网络和处理器资源，所以通常仅当用户使用WiFi时才进行。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;优化移动端浏览体验是Chrome开发团队的首要优先任务之一，我们可以期待在未来几个月或几年内看到新的改进。实际上，这是一个值得单独行文介绍的内容——或许在POSA系列的下一版中就会出现。&lt;/p&gt;
&lt;h2 id=&quot;使用Chrome预测器进行推测优化&quot;&gt;&lt;a href=&quot;#使用Chrome预测器进行推测优化&quot; class=&quot;headerlink&quot; title=&quot;使用Chrome预测器进行推测优化&quot;&gt;&lt;/a&gt;使用Chrome预测器进行推测优化&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Chrome会随着你的使用变得越来越快。这项本领是借助&lt;code&gt;Predictor&lt;/code&gt;单例对象实现的，它在浏览器内核进程中被实例化，其唯一职责是观测网络模式，并学习和预测未来可能出现的用户行为。&lt;code&gt;Predictor&lt;/code&gt;处理信号的一些例子有：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用户鼠标在一个链接上悬停，很好地预示了接下来可能发生的浏览行为，Chrome可以发起一个推测的目标主机DNS查询，还有可能开始TCP握手，以提升速度。待用户实际点击时，这平均还需要约200毫秒的时间，我们很有可能已经完成了DNS和TCP的步骤，这就为这次浏览减少了数百毫秒的额外延迟时间。&lt;/li&gt;
&lt;li&gt;在Omnibox（URL）栏中键入内容将触发高概率建议，也会触发DNS查询、TCP预连接甚至在隐藏的标签页中预呈现该页面。&lt;/li&gt;
&lt;li&gt;我们都有一个每天访问的喜爱站点清单。Chrome可以学习这些站点的子资源并推测性地进行预解析，甚至可能预获取这些资源来加速浏览。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Chrome会随着你的使用，逐步学习网络的拓扑结构和你的浏览模式。如果顺利，它可以为每次浏览减少数百毫秒的延迟，让用户更加接近“页面即刻加载”的理想状态。为了实现这一点，Chrome使用了四个核心的优化技术，见下表：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;技术&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DNS预解析&lt;/td&gt;
&lt;td&gt;提前解析主机名，避免DNS延迟&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TCP预连接&lt;/td&gt;
&lt;td&gt;提前连接目标服务器，避免TCP握手的延迟&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;资源预获取&lt;/td&gt;
&lt;td&gt;提前获取页面上的关键资源，加速页面的呈现&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;页面预呈现&lt;/td&gt;
&lt;td&gt;提前获取整个页面的所有资源，用户触发时立即展示&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;每个触发这些技术的决定都是在大量约束条件下优化判断的。毕竟，每一项优化都是推测性的，这意味着如果运用失当，可能会导致不必要任务和网络流量，更糟的是，还有可能对用户实际浏览行为的加载时间产生负面效果。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Chrome是如何解决这个问题的呢？预测器会尽可能多地吸收信号，包括用户产生的行为、历史浏览数据以及来自呈现器和网络栈本身的信号。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;与&lt;code&gt;ResourceDispatcherHost&lt;/code&gt;负责协调Chrome中所有网络活动的情况类似，&lt;code&gt;Predictor&lt;/code&gt;对象也在Chrome内部创建了对一些用户和网络产生活动的过滤器：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;IPC频道过滤器，监测来自呈现进程的信号&lt;/li&gt;
&lt;li&gt;为各个请求添加ConnectInterceptor对象，这样它就能观测每个请求的流量模式并记录成功次数。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;下面是一个实际操作的例子，呈现进程可以发出一条带有以下任何提示的消息给浏览器进程，这些提示定义在ResolutionMotivation（url_info.h）中：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;enum&lt;/span&gt; ResolutionMotivation &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  MOUSE_OVER_MOTIVATED,     &lt;span class=&quot;comment&quot;&gt;// Mouse-over initiated by the user.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  OMNIBOX_MOTIVATED,        &lt;span class=&quot;comment&quot;&gt;// Omnibox suggested resolving this.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  STARTUP_LIST_MOTIVATED,   &lt;span class=&quot;comment&quot;&gt;// This resource is on the top 10 startup list.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  EARLY_LOAD_MOTIVATED,     &lt;span class=&quot;comment&quot;&gt;// In some cases we use the prefetcher to warm up&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            &lt;span class=&quot;comment&quot;&gt;// the connection in advance of issuing the real&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            &lt;span class=&quot;comment&quot;&gt;// request.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;// The following involve predictive prefetching, triggered by a navigation.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;// The referring_url_ is also set when these are used.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  STATIC_REFERAL_MOTIVATED,  &lt;span class=&quot;comment&quot;&gt;// External database suggested this resolution.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  LEARNED_REFERAL_MOTIVATED, &lt;span class=&quot;comment&quot;&gt;// Prior navigation taught us this resolution.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  SELF_REFERAL_MOTIVATED,    &lt;span class=&quot;comment&quot;&gt;// Guess about need for a second connection.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;// &amp;lt;snip&amp;gt; ...&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;收到这样的信号后，预测器的目标是评价其成功的可能性，然后在资源可用的情况下触发相应行为。每条提示可能都有一个成功概率、一个优先级和一个过期时间戳，这组数据可用于维护一个推测优化的内部优先级队列。最后，对于每条从此队列发出的请求，预测器还能够跟踪记录其成功率，这又被用于未来决策的优化中。&lt;/p&gt;
&lt;h2 id=&quot;Chrome网络架构概要&quot;&gt;&lt;a href=&quot;#Chrome网络架构概要&quot; class=&quot;headerlink&quot; title=&quot;Chrome网络架构概要&quot;&gt;&lt;/a&gt;Chrome网络架构概要&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Chrome使用多进程架构，将呈现进程与浏览器进程隔离开。&lt;/li&gt;
&lt;li&gt;Chrome保持资源调度器的一个单一实例，它被所有呈现进程所共享，运行在浏览器内核进程中。&lt;/li&gt;
&lt;li&gt;网络栈是一个跨平台、几乎单线程的库。&lt;/li&gt;
&lt;li&gt;网络栈使用非阻塞操作来管理所有网络操作。&lt;/li&gt;
&lt;li&gt;共享的网络栈可实现高效的资源次序优先化、重用并使浏览器可以在所有运行的进程之间进行全局性的优化。&lt;/li&gt;
&lt;li&gt;各个呈现进程通过IPC与资源调度器通信。&lt;/li&gt;
&lt;li&gt;资源调度器通过自定义的IPC过滤器截获资源请求。&lt;/li&gt;
&lt;li&gt;预测器截获资源请求和响应通信来学习和优化未来的网络请求。&lt;/li&gt;
&lt;li&gt;预测器根据所学的浏览模式可能推测性地安排DNS、TCP甚至资源请求的计划，当用户实际发生行为时节省数百毫秒的时间。&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;浏览器会话的生命周期&quot;&gt;&lt;a href=&quot;#浏览器会话的生命周期&quot; class=&quot;headerlink&quot; title=&quot;浏览器会话的生命周期&quot;&gt;&lt;/a&gt;浏览器会话的生命周期&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;有了对Chrome网络栈架构的一个概括性认识后，我们接下来仔细研究一下浏览器内部实施的各种面向用户的优化。具体而言，假设我们刚创建了一个新的Chrome profile，准备好开始了。&lt;/p&gt;
&lt;h2 id=&quot;优化冷启动体验&quot;&gt;&lt;a href=&quot;#优化冷启动体验&quot; class=&quot;headerlink&quot; title=&quot;优化冷启动体验&quot;&gt;&lt;/a&gt;优化冷启动体验&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当你第一次加载浏览器时，它对你的喜爱站点和浏览模式一无所知。但是，我们中的很多人都会在浏览器冷启动后做同样的事：我们会浏览我们的电邮收件箱、喜爱的新闻站点、社交网站、内网入口等等。具体的站点可能因人而异，但是这些会话的相似之处使Chrome的Predictor可以加速你的冷启动过程。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Chrome会记住用户在浏览器启动后前10个最有可能访问的主机名——注意这并不是前10个全局目标站点，而特指全新开启浏览器之后的目标站点。浏览器加载时，Chrome可以为这些可能的目标站点触发DNS预获取行为。如果你对此感兴趣，可以打开一个新标签页浏览地址&lt;code&gt;chrome://dns&lt;/code&gt;，看一看你自己的启动主机名列表。在页面顶端，你会找到你profile的前10个最可能启动站点。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Chromium%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%90%AF%E5%8A%A8%E7%AF%87/dns.jpg&quot; alt=&quot;启动DNS&quot;&gt;&lt;/p&gt;
&lt;p&gt;截图是我的Chrome profile的例子。我通常是如何开始浏览的呢，如果我在写文章，比如现在这一篇，可能会频繁访问Google Docs。果不其然，我们在列表中看到很多Google的主机名。&lt;/p&gt;
&lt;h2 id=&quot;使用Omnibox优化交互过程&quot;&gt;&lt;a href=&quot;#使用Omnibox优化交互过程&quot; class=&quot;headerlink&quot; title=&quot;使用Omnibox优化交互过程&quot;&gt;&lt;/a&gt;使用Omnibox优化交互过程&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Chrome的创新之一是引入了Omnibox，它与此前的地址栏不同，可以处理目标站点URL之外的很多东西。除了记住用户曾经访问过的页面的URL之外，它还提供完整的对历史记录的文本检索功能，与你所选择的搜索引擎的集成性也较好。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;随着用户在其中键入内容，Omnibox会自动提供建议的行为，可能是基于你的浏览历史的URL或者是一次检索查询。在后台，每个建议行为都根据查询结果和历史表现进行评分。实际上，Chrome允许我们通过访问&lt;code&gt;chrome://predictors&lt;/code&gt;来查看这些数据。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Chromium%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%90%AF%E5%8A%A8%E7%AF%87/Omnibox.png&quot; alt=&quot;Omnibox的URL预测&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Chrome会维护用户输入前缀、建议行为以及每一记录的命中率的历史记录。在我的profile中，你可以看到当我在Omnibox中输入“g”时，有76%的可能性我是要访问Gmail。而当我加了一个“m”之后（变成“gm”），则置信水平上升到99.8%，实际上，在记录的412次访问中，我只有一次在输入“gm”之后没有访问Gmail。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这与网络栈有什么关系呢？可能备选站点中黄色和绿色的记录也是&lt;code&gt;ResourceDispatcher&lt;/code&gt;的重要信号。如果我们有一个可能的备选站点（黄色），Chrome可能为该目标主机触发DNS预获取。如果我们有一个高度确信的备选站点（绿色），那么Chrome可能还会在主机名解析之后触发TCP预连接。最后，如果这两步都做完时用户还没做出最终决定，那么Chrome甚至可能在隐藏的标签页中预呈现整个页面。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;另一方面，如果根据过去的浏览历史没有为所输入的前缀找到较好的匹配，那么Chrome预计可能会发生检索请求，会向你的搜索引擎发起DNS预获取和TCP预连接。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;一个普通用户需要花费数百毫秒来填写查询内容，评价所给出的自动补全建议。在后台，Chrome能够预获取、预连接，并在某些情况下对页面进行预呈现，这样当用户准备好按下“输入”键时，很多网络延迟已经被消除了。&lt;/p&gt;
&lt;h2 id=&quot;优化缓存性能&quot;&gt;&lt;a href=&quot;#优化缓存性能&quot; class=&quot;headerlink&quot; title=&quot;优化缓存性能&quot;&gt;&lt;/a&gt;优化缓存性能&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;最好最快的请求是不发出请求。当我们说到性能时必然会涉及缓存的问题——你正在为你网页上的所有资源提供&lt;code&gt;Expires、ETag、Last-Modified和Cache-Control&lt;/code&gt;这些&lt;a href=&quot;https://developers.google.com/speed/docs/insights/LeverageBrowserCaching&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;响应标头&lt;/a&gt;，对吧？如果你没有这样做，请立刻去改。我们会等你。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Chrome的内部缓存有两种不同的实现方式：一种是由本地磁盘所支持，另一种是把所有内容存储在内存中。内存实现方式用于&lt;a href=&quot;http://support.google.com/chrome/bin/answer.py?hl=en&amp;amp;answer=95464&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;匿名浏览模式&lt;/a&gt;，当你关闭窗口后会把痕迹清除干净。两种方式都实现相同的内部接口（&lt;code&gt;disk_cache:Backend&lt;/code&gt;和&lt;code&gt;disk_cache:Entry&lt;/code&gt;），这极大地简化了架构并且——如果你非要坚持的话——允许你很方便地试验你自己的缓存实现。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;内部来看，磁盘缓存实现了其自己的数据结构，它们都被存储在你的profile的一个单独的缓存文件夹中。这个文件夹中有索引文件，它们在浏览器启动时进行内存映射，还有数据文件，它们存储了实际数据以及HTTP标头和其他簿记信息【注4】。最后，在缓存回收机制上，磁盘缓存会维护一个最近最少使用（LRU）缓存，它会把访问频度和资源新旧度等排序量化指标考虑进去。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果你对Chrome的缓存状态很感兴趣，可以打开新标签页访问&lt;code&gt;chrome://net-internals/#httpCache&lt;/code&gt;。或者，如果你想看看真实的HTTP元数据以及缓存的响应，也可以访问&lt;code&gt;chrome://cache&lt;/code&gt;，其中列示了缓存中当前可用的所有资源。在该页面中，检索一项资源之后可以点击URL查看缓存的标头和响应的具体字节内容。&lt;/p&gt;
&lt;h2 id=&quot;使用预获取优化DNS&quot;&gt;&lt;a href=&quot;#使用预获取优化DNS&quot; class=&quot;headerlink&quot; title=&quot;使用预获取优化DNS&quot;&gt;&lt;/a&gt;使用预获取优化DNS&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们已经在一些地方提到过DNS预解析，所以在我们深入介绍它的实现方式之前，先回忆一下哪些情况下为什么会触发它：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;运行在呈现进程中的Blink文档解析器，可以提供当前页面上所有链接的主机名清单，Chrome可以从中选择提前解析。&lt;/li&gt;
&lt;li&gt;呈现进程会将鼠标悬停和“按下按键”事件作为用户意图进行浏览的前期信号，从而触发预解析。&lt;/li&gt;
&lt;li&gt;Omnibox根据高度可能的建议，可能触发解析请求。&lt;/li&gt;
&lt;li&gt;Predictor基于过去的浏览和资源请求数据，可能请求主机名解析。&lt;/li&gt;
&lt;li&gt;页面所有者可能明确指示Chrome应该预解析哪些主机名。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所有情况下，DNS预解析都被作为提示来处理。Chrome并不保证预解析必然进行，而是综合运用各个信号与其自身的预测器来评估这条提示并动态决策。在“最坏情况”下，如果Chrome未能及时完成主机名预解析，用户就要等待显式DNS解析，接着是TCP连接时间，最后是实际资源获取。但是，如果出现了这种情况，预测器会进行记录并相应调整其未来决策——随着你的持续使用，它会变得更快更聪明。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们此前没有提到的一项优化是Chrome能够学习每个站点的拓扑结构，并运用这项信息来加速未来的访问过程。具体而言，回忆一下，一个页面平均由88项资源组成，由15个以上不同的主机发送。每一次你进行浏览，Chrome会记录页面上的热门资源的主机名，在以后的访问中，它可能会对其中一些或全部选择触发DNS预解析甚至TCP预连接。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;访问&lt;code&gt;chrome://dns&lt;/code&gt;并检索你profile对应的热门站点主机名，可以查看Chrome所保存下来的子资源主机名。在上面的例子中，你可以看到Chrome记录了Google+的6个子资源主机名，还统计了DNS预解析触发或TCP预连接执行的次数，还有会由各项处理的请求的估计值。这些内部记录帮助Chrome预测器实现优化。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;除了这些内部信号之外，站点的所有者也能在页面中嵌入附加的标记请求浏览器预解析一个主机名：&lt;/p&gt;
&lt;figure class=&quot;highlight htmlbars&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;name&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;rel&lt;/span&gt;=&lt;span class=&quot;string&quot;&gt;&quot;dns-prefetch&quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;href&lt;/span&gt;=&lt;span class=&quot;string&quot;&gt;&quot;//host_name_to_prefetch.com&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;为何不直接依靠浏览器的自动机制呢？有些时候，你可能希望解析一个页面中任何地方都没有提到过的主机名。重定向就是一个典型的例子：链接可能指向一个主机——就如同一项分析追踪服务一样——这个主机再把用户重定向至真正的目标站点。Chrome依靠自身是无法推断出这种模式的，但你可以手动提供一条提示帮助它，让浏览器提前解析真实目标站点的主机名。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这一切在后台是如何实现的呢？和我们讨论过的其他优化手段一样，这个问题的答案也取决于Chrome的版本，因为开发团队一直试验新的、更好的方式来提升性能。但是，不严格地说，Chrome内部的DNS基础设施有两个主要的实现方式。过去，Chrome依靠操作平台无关的系统调用&lt;code&gt;getaddrinfo&lt;/code&gt;，并把DNS查询的实际职责交由操作系统完成。但是，这种方式正逐步被Chrome自己实现的异步DNS解析器所替代。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;依靠操作系统的原有方式具有其优点：代码少而简单，并能够利用操作系统的DNS缓存。但是，&lt;code&gt;getaddrinfo&lt;/code&gt;也是一个阻塞型的系统调用，这意味着Chrome必须创建并维护一个专用的worker线程池，才能够实现多条并行查询。这个未连接池最多只能容纳六个线程，这个上限是基于硬件的最小公分母得出的经验数字——这样并行请求的数量超出的话，有些用户的路由器就会过载。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;对于使用worker池的预解析，Chrome就只是调度&lt;code&gt;getaddrinfo&lt;/code&gt;调用，这会一直阻塞worker线程，直至响应就绪后马上丢弃所返回的结果，并开始处理下一条预获取请求。结果由操作系统的DNS缓存来存储，未来实际进行getaddrinfo查询时，它会立即返回响应。这种方式简单有效，实践中的表现也不错。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;但这还不够好。&lt;code&gt;getaddrinfo&lt;/code&gt;调用有很多有用信息不向Chrome公开，比如每条记录的生存时间（TTL）时间戳，以及DNS缓存本身的状态。为了提升性能，Chrome团队决定自己来实现跨平台的异步DNS解析器。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Chromium%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%90%AF%E5%8A%A8%E7%AF%87/flags.jpg&quot; alt=&quot;启用异步DNS解析器&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;通过把DNS解析放到Chrome内部来处理，新的异步解析器可以实现一些新的优化手段：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;更好控制重传计时器，能够并行执行多条查询&lt;/li&gt;
&lt;li&gt;记录生存时间的可见性，使得Chrome能提前刷新热点记录&lt;/li&gt;
&lt;li&gt;更好的双栈实现（IPv4和IPv6）行为&lt;/li&gt;
&lt;li&gt;基于RTT或其他信号的，对不同服务器的故障切换&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;以上所有以及其他很多想法都是在Chrome内持续试验并优化的。这就必然涉及一个问题：我们如何了解并衡量这些想法的效果呢？很简单，Chrome会为每个profile分别记录详细的网络性能统计数据和直方图。要查看所收集到的DNS统计数据，可以打开新标签页，访问&lt;code&gt;chrome://histograms/DNS&lt;/code&gt;（见下图）&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Chromium%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%90%AF%E5%8A%A8%E7%AF%87/dnsget.jpg&quot; alt=&quot;DNS预获取的直方图&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面的直方图显示出了DNS预获取请求延迟的分布情况：大约50%的（最右侧列）预获取查询在20毫秒内完成（最左侧列）。注意，这是基于最近的浏览会话（9869个样本）的统计得到的，并属于用户的隐私数据。如果该用户选择报告Chrome的使用统计数据，则这些数据的摘要会被匿名处理，定期反馈给开发团队，他们就可以看到试验的效果并进行相应的调整。&lt;/p&gt;
&lt;h2 id=&quot;使用预连接优化TCP连接管理&quot;&gt;&lt;a href=&quot;#使用预连接优化TCP连接管理&quot; class=&quot;headerlink&quot; title=&quot;使用预连接优化TCP连接管理&quot;&gt;&lt;/a&gt;使用预连接优化TCP连接管理&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们已经预解析了主机名，按照Omnibox或Chrome预测器的估计，我们很有可能即将进行浏览行为。为什么不更进一步，也推测性地预连接到目标主机，在用户发出请求之前完成TCP握手的步骤呢？这样一来，我们又能消除掉一个往返延迟，轻松省去用户数百毫秒的时间。没错，TCP预连接正是这样做的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;打开新标签页访问&lt;code&gt;chrome://dns&lt;/code&gt;可以查看已经触发TCP预连接的主机。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Chromium%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%90%AF%E5%8A%A8%E7%AF%87/dnshost.jpg&quot; alt=&quot;展示已经触发TCP预连接的主机&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;首先，Chrome会检查socket池，看看是否有该主机名的可用socket可供重用——存活socket会在池中留存一段时间，以避免TCP握手和慢热启动的惩罚时间。如果没有socket可用，则由其发起TCP握手并放入池中。然后，当用户进行浏览时，HTTP请求就可以立刻调度。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Chrome在&lt;code&gt;chrome://net-internals#sockets&lt;/code&gt;中提供了一个工具可以查看Chrome中所有已开启socket的状态。图1.10是相关的截图。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Chromium%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%90%AF%E5%8A%A8%E7%AF%87/socketopen.jpeg&quot; alt=&quot;已开启的socket&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;你还可以详细查看每个socket，检查时间线：连接和代理时间，每个包的到达时间等等。最后要说的很重要的一点是：你也可以导出这些数据进行后续分析或报告bug。具有良好的信息统计机制对任何优化都是很关键的，&lt;code&gt;chrome://net-internals&lt;/code&gt;就是Chrome中所有功能相互作用的集中展示——如果你还没探索过这个功能，你应该试试！&lt;/p&gt;
&lt;h2 id=&quot;使用预获取提示优化资源加载&quot;&gt;&lt;a href=&quot;#使用预获取提示优化资源加载&quot; class=&quot;headerlink&quot; title=&quot;使用预获取提示优化资源加载&quot;&gt;&lt;/a&gt;使用预获取提示优化资源加载&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;有时，页面的作者能够提供基于其站点结构或布局附加的导航或页面上下文，帮助浏览器优化用户体验。Chrome支持两种这样的提示，可以嵌入页面标记中使用：&lt;/p&gt;
&lt;figure class=&quot;highlight htmlbars&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;name&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;rel&lt;/span&gt;=&lt;span class=&quot;string&quot;&gt;&quot;subresource&quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;href&lt;/span&gt;=&lt;span class=&quot;string&quot;&gt;&quot;/javascript/myapp.js&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;name&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;rel&lt;/span&gt;=&lt;span class=&quot;string&quot;&gt;&quot;prefetch&quot;&lt;/span&gt;    &lt;span class=&quot;attr&quot;&gt;href&lt;/span&gt;=&lt;span class=&quot;string&quot;&gt;&quot;/images/big.jpeg&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;子资源和预获取看起来非常类似，但是语义完全不同。当链接资源指定其关系为“预获取”时，它是告诉浏览器，这项资源在以后的浏览中可能用到。换言之，这实际上是一个跨页面提示。而当资源指定其关系为“子资源”时，它是提前告诉浏览器该资源会在当前页面中被用到，在该文档后面的部分遇到它之前可以先发起请求。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;可以想见，两者的不同语义会导致资源加载器的行为大相径庭。标记预获取的资源会被看做优先级较低，并在当前页面加载完成后由浏览器进行一次下载。标记为子资源的内容一旦遇到就会作为高优先级资源来获取，并与当前页面上的其余资源相互竞争。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这两种提示如果使用得当可以极大地帮助优化你站点的用户体验。最后，还要注意，预获取是&lt;a href=&quot;https://whatwg.org/specs/web-apps/current-work/multipage/links.html#link-type-prefetch&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;HTML5规范的一部分&lt;/a&gt;，目前Firefox和Chrome都支持，而子资源目前&lt;a href=&quot;http://www.chromium.org/spdy/link-headers-and-server-hint/link-rel-subresource&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;只限于Chrome&lt;/a&gt;。&lt;/p&gt;
&lt;h2 id=&quot;使用浏览器预刷新优化资源加载&quot;&gt;&lt;a href=&quot;#使用浏览器预刷新优化资源加载&quot; class=&quot;headerlink&quot; title=&quot;使用浏览器预刷新优化资源加载&quot;&gt;&lt;/a&gt;使用浏览器预刷新优化资源加载&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;不巧的是，不是所有站点所有者都能够或愿意在标记中为浏览器提供子资源提示。而且，即使他们这样做，我们还是要等待HTML文档从服务器传送过来之后才能解析这些提示，开始获取这些必要的子资源——根据服务器响应时间和客户端与服务器间的延迟，这可能需要耗费数百乃至数千毫秒。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;但是，我们前面看到，Chrome已经通过学习常用资源的主机名来执行DNS预获取了。那么，为什么不如法炮制，更进一步：执行DNS查询，使用TCP预连接然后也推测性地预获取资源呢？没错，这就是预刷新的作用：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用户发起对目标URL的请求&lt;/li&gt;
&lt;li&gt;Chrome询问预测器其所学习到的与目标URL相关的子资源，并发起DNS预获取、TCP预连接和资源预刷新等一连串行为&lt;/li&gt;
&lt;li&gt;如果所学到的子资源在缓存中，则将其从磁盘加载到内存中&lt;/li&gt;
&lt;li&gt;如果所学到的子资源缺失，或者已过期，则进行一次网络请求&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;资源预刷新是展示Chrome中每个试验性优化手段的工作流的绝佳例子——理论上讲，一项优化应该使性能得到提升，但是也涉及很多因素的此消彼长。只有一种方式能够可靠地确定一项优化是不是有效，是不是适合于Chrome：先实现它，并在一些预先发布的渠道（真正的网络、真实浏览模式、真人用户）上进行A/B试验。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在2013年初，Chrome团队还处于讨论这种实现的早期阶段。如果根据所收集的结果它能奏效，我们我们可能会在年内晚些时候在Chrome中看到预刷新。Chrome的网络性能优化从未止步——开发团队一直在试验新的方法、创意和技术。&lt;/p&gt;
&lt;h2 id=&quot;使用预呈现优化浏览&quot;&gt;&lt;a href=&quot;#使用预呈现优化浏览&quot; class=&quot;headerlink&quot; title=&quot;使用预呈现优化浏览&quot;&gt;&lt;/a&gt;使用预呈现优化浏览&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;目前为止我们介绍过的每一项优化都是帮助减少用户进行浏览的直接请求和标签页上呈现最终页面之间的延迟的。但是，要真正得到即刻展示页面的体验，需要什么呢？根据我们之前看到的UX数据，这样的交互时间需要低于100毫秒，这样，留给网络延迟的余地可不算多。我们怎么才能在100毫秒内把呈现好的页面展示出来呢？&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当然，你已经知道答案了，因为这是很多用户所用的共同模式：如果你打开多个标签页，标签页间的切换就是即刻的，比在一个前景标签页中浏览同样资源之间的等待要快得多。那么，如果浏览器提供一个API来实现这一点呢？&lt;/p&gt;
&lt;figure class=&quot;highlight htmlbars&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;name&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;rel&lt;/span&gt;=&lt;span class=&quot;string&quot;&gt;&quot;prerender&quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;href&lt;/span&gt;=&lt;span class=&quot;string&quot;&gt;&quot;http://example.org/index.html&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;你可能猜到了，这就是Chrome中的&lt;a href=&quot;https://developers.google.com/chrome/whitepapers/prerender&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;预呈现&lt;/a&gt;。不是如“预获取”提示实现的那样只下载单项资源，“预呈现”属性命令Chrome在隐藏标签页中预呈现页面以及所有子资源。隐藏标签页本身对用户不可见，但当用户触发浏览行为时，该标签页就会从后台切换出来实现“即刻体验”。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;想看看这是如何实现的吗？可以访问prerender-test.appspot.com上还在开发中的演示版，要查看你的profile的预呈现页面的历史记录和状态，访问：&lt;code&gt;chrome://net-internals/#prerender&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Chromium%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%90%AF%E5%8A%A8%E7%AF%87/prerender.jpg&quot; alt=&quot;当前profile的预呈现页面&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;可以预见的是，在隐藏标签页中呈现完整页面可能会耗费CPU和网络的大量资源，所以仅当我们高度确信应该使用隐藏标签页时才应该使用。例如，当你使用Omnibox时，对高度确信的建议可能会触发预呈现。类似地，Google搜索如果估计认为它的第一条检索结果是高度确信的目标站点，有时会在其标记中添加预呈现提示（也称为Google即开页面）。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;你还可以为自己的站点添加预呈现提示。在你这样做之前，请先了解并记住预呈现过程具有的以下局限之处：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;所有线程总共至多只能有一个预呈现标签页&lt;/li&gt;
&lt;li&gt;HTTPS和需要HTTP身份鉴证的页面不能使用&lt;/li&gt;
&lt;li&gt;如果所请求资源或其任何子资源需要进行非幂等请求（只允许GET请求），预呈现会被放弃&lt;/li&gt;
&lt;li&gt;所有资源都以最低的网络优先级进行获取&lt;/li&gt;
&lt;li&gt;该页面以最低的CPU优先级进行呈现&lt;/li&gt;
&lt;li&gt;如果内存需求超过100MB则该页面会被放弃&lt;/li&gt;
&lt;li&gt;插件初始化被推迟，如果出现了HTML5的多媒体元素则预呈现被放弃&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;换言之，预呈现不保证一定发生，并只适用于安全的页面。此外，因为JavaScript和其他逻辑可能在隐藏页面中被执行，实践中最好使用页面&lt;a href=&quot;https://developers.google.com/chrome/whitepapers/pagevisibility&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;可见性API&lt;/a&gt;来检测一下该页面是否可见——&lt;a href=&quot;https://www.html5rocks.com/en/tutorials/pagevisibility/intro/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;这是你本就应该做的&lt;/a&gt;。&lt;/p&gt;
&lt;h1 id=&quot;Chrome会随着你的使用越来越快&quot;&gt;&lt;a href=&quot;#Chrome会随着你的使用越来越快&quot; class=&quot;headerlink&quot; title=&quot;Chrome会随着你的使用越来越快&quot;&gt;&lt;/a&gt;Chrome会随着你的使用越来越快&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;无需多言，Chrome的网络栈绝非一个简单的socket管理器。我们这次走马观花的概述介绍了在网站浏览的背后多层次的透明运行的优化手段。Chrome对网站拓扑结构和你的浏览模式了解越是深入，它的效果就越好。就像魔法一样，Chrome会随着你的使用越来越快。可你知道它并不是魔法，你了解这背后的机制。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;最后，还要注意一点，Chrome团队持续试验着优化性能的新想法——这个过程从未停止。在你阅读本文时，就可能有新的试验项目和优化手段正在开发、测试或部署着。也许只有当我们能够对每个站点每个页面都实现即刻加载（小于100毫秒）时，才会停下脚步吧。在那之前，总有工作等着我们去完成。&lt;/p&gt;
&lt;h1 id=&quot;学习浏览器技术可以得到什么？&quot;&gt;&lt;a href=&quot;#学习浏览器技术可以得到什么？&quot; class=&quot;headerlink&quot; title=&quot;学习浏览器技术可以得到什么？&quot;&gt;&lt;/a&gt;学习浏览器技术可以得到什么？&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;浏览器要处理的两个核心对象是HTML和JavaScript。HTML用来实现网页UI，涉及到的最核心技术是UI渲染技术。JavaScript用来实现网页功能，涉及到的最核心技术JavaScript引擎技术。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;一切带有屏幕的智能设备，UI都是其所运行系统的一个核心模块，它负责与用户进行交互，以及将交互结果反馈给用户，从而形成一个闭环。用户在使用一个系统的时候，最先接触到的就是它的UI，经常接触的也是它的UI，因此UI的好坏直接就影响到了系统用户体验的好坏。用户体验对一个系统来说是至关重要的，例如，很多人觉得iOS系统比Android系统好用的其中一个原因就是前者的用户体验更好。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;衡量一个系统的用户体验好与坏的其中一个重要标准就是UI的流畅与否，其中又以动画的流畅与否为核心，因为一个流畅的动画显示需要的UI渲染速度是60fps。为了达到60fps的渲染速度，各个系统在实现UI模块的时候，可谓是费尽心思、尽其所能。通常都会使用诸如纵向分层、横向分块的渲染策略。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所谓纵向分层，就是在Z轴方向上按层来划分UI，这样带来的好处在渲染UI的每一帧时，不必每一层都进行重绘。这种分层渲染策略使用到了一种称为“绘制-合成”的UI渲染技术。也就是各层负责绘制好自己的UI，然后再由一个单独的模块对它们进行合成。这样在渲染UI的每一个帧时，只有UI发生了变化的层才需要重新进行绘制，没有发生UI变化的层只需要参与合成这一步即可。这种技术可以大大地减少渲染操作，从而获得更流畅的UI体验。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所谓横向分块，就是对于UI的每一个层，按照一定的规则对其进行分块，这样带来的好处就是在渲染UI的每一帧遇到一个需要进行重新绘制的层时，不必对该层的所有内容都进行重新绘制，只需要绘制那些在可视区间的块即可。这样也可以在某种程度上减少渲染操作，从而获得更流畅的UI体验。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;现在的智能设备配备的CPU都是多核的。为了能够充分地利用CPU多核特性，一帧UI渲染通常分两步进行：第一步是收集UI绘制命令；第二步是执行UI绘制命令。每一步都是在一个独立的线程完成，因此就可以充分地利用CPU的多核特性：在执行第N帧的UI绘制命令的同时，收集第N+1帧的UI绘制命令。此外，对于第一步收集到的UI绘制命令，还可以做一些额外的优化。当我们收集到一帧UI的所有绘制命令的时候，我们就相当于是知悉了这一帧UI的全貌。知悉了一个UI帧的全貌之后，就可以进行一些优化，例如对某些UI绘制命令进行重排和合并，以及丢弃那些被遮挡的UI相关的绘制命令。这些优化同样是可以减少渲染操作，从而获得更流畅的UI体验。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;现在的智能设备，很多都配备了GPU，这意味着我们可以使用GPU进一步提高UI的渲染速度，这就是所谓的硬件加速渲染技术。例如对于我们前面提到的UI层和块，可以直接以GPU的纹理或者FBO来进行绘制和合成。GPU具有成熟和专业的UI渲染技术，因此通过它来渲染UI，可以获得更流畅的UI体验。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;以上提及到的所有UI渲染技术，不管是什么系统，我们都可以或多或少地看到它们的影子，因此它们都是通用的、现代化的UI渲染技术。如果掌握了这些UI渲染技术，那么不管以后流行的是什么系统，我们都可以轻松应对。因此，学习浏览器技术可以得到的第一点核心技术就是现代化的先进UI渲染技术。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;不知道同学们有没有发现，最近几年时不时都看到有新的编程语言发布，特别是伴随着新系统的发布，其中比较有名的就是Google的Go语言和Apple的Swift语言。我们在惊叹这些编程语言方便好用的同时，有没有想过它们背后是如何设计和实现的呢？如果有考虑过这个问题的话，我们就不得不提到JavaScript这个古老而又流行的编程语言。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;JavaScript被视为一个“玩具语言”，据说它只花了2个星期设计，然后被使用了20年。在20年的时间里，大家一边在用它，然后又一边在骂它。这足见大家是有多么的喜欢它，正所谓”骂是爱，打是亲“嘛。JavaScript虽然天生是为操作网页而设计的，但是它并不仅仅是应用在网页前端应用开发上，它还渗透了移动端和服务端应用开发上。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在移动端上，近两三年出现了不少专门针对手机的Web OS，例如Firefox OS、Ubuntu Mobile OS、Tizen OS以及阿里的云OS，都支持运行Web应用，这意味在这些系统上可以使用JavaScript来开发应用。当然，在Android和iOS上也可以开发Web应用，不过它们都是要运行在WebView之上，不是直接在OS层面上得到支持。在服务端上，Node.js就是一个有代表性的框架，它使得我们可以使用JavaScript来开发Web服务器。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;除了在移动端和服务端上，JavaScript甚至还应用在MCU（Microcontroller Unit）领域上，也就是俗称的单片机领域上。这些MCU提供了一个JavaScript运行环境，从而使得我们可以使用JavaScript操作它们。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;一个本来只是设计用在网页开发的语言，由于它的简洁和易用性，现在不仅渗透到移动端、服务器端开发上，还渗透到了MCU领域上，这足以看到JavaScript是如此广泛地被开发者接受和使用。当然，JavaScript广泛地被开发者接受和使用，并不意味着它是完美的，例如性能就是一个比较突出的问题。但是会不会在以后的某一天，当JavaScript的性能问题被解决之后，所有能够编程的领域，都会被JavaScript代替呢？&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;不管如何，鉴于现在JavaScript的流行性，作为一个软件开发从业者，我们不仅会使用JavaScript，还需要知道JavaScript在背后是如何运行的，这样才能达到一个更高的境界。JavaScript是一种动态语言，与C/C++、Java这些静态语言一样，在实现上都是涉及到了编译相关的知识，例如语法解析、生成语法树、生成字节码指令、生成本地指令和指令优化等。只不过对于动态语言来说，这些操作发生在应用程序运行时，只对于静态语言来说，这些操作发生应用程序运行前。此外，运行JavaScript的引擎与运行Java字节码的虚拟机一样，在运行时都提供了内存自动管理技术，也就是会执行GC。由此可见，学习JavaScript可以获得很多编译语言相关的知识。这也是学习浏览器技术可以得到的第二点核心技术。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当我们学习的是基于Chromium的浏览器技术的时候，我们就不仅仅是可以获得上面提到的两个核心技术，还可以学习到一个复杂系统的架构，例如它的对象管理技术、多进程架构和多线程编程模型等等。一言蔽之，学习浏览器技术可以使我们获得很多现在和甚至未来都流行的计算机技术。&lt;/p&gt;
&lt;h1 id=&quot;注释&quot;&gt;&lt;a href=&quot;#注释&quot; class=&quot;headerlink&quot; title=&quot;注释&quot;&gt;&lt;/a&gt;注释&lt;/h1&gt;&lt;ol&gt;
&lt;li&gt;第10章：《移动网络性能的秘密》详细解释了这个问题。&lt;/li&gt;
&lt;li&gt;如果你感兴趣，Chromium的百科页面上有详细的介绍。&lt;/li&gt;
&lt;li&gt;Http://code.google.com/searchframe#OAMlx_jo-ck/src/content/public/browser/resource_dispatcher_host.h&amp;amp;exact_package=chromium&amp;amp;q=ResourceDispatcherHost.&lt;/li&gt;
&lt;li&gt;16KB以内的资源保存在共享数据块文件中，更大的文件在磁盘上有自己的专用文件。&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&quot;参考&quot;&gt;&lt;a href=&quot;#参考&quot; class=&quot;headerlink&quot; title=&quot;参考&quot;&gt;&lt;/a&gt;参考&lt;/h1&gt;&lt;p&gt;&lt;a href=&quot;http://aosabook.org/en/posa/high-performance-networking-in-chrome.html&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;http://aosabook.org/en/posa/high-performance-networking-in-chrome.html&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://www.cnbeta.com/articles/tech/63690.htm&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;https://www.cnbeta.com/articles/tech/63690.htm&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Chromium%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%90%AF%E5%8A%A8%E7%AF%87/meizi.jpeg&quot; alt=&quot;妹子图&quot;&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;深思熟虑之后，觉得有必要学一下UI渲染技术和JS引擎技术，为以后的跨平台实现打下坚实的基础。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;本篇是一篇科普，将打开苦逼又刺激的Chromium学习之路。&lt;br&gt;
    
    </summary>
    
      <category term="Chromium" scheme="http://windrunnerlihuan.com/categories/Chromium/"/>
    
    
      <category term="Chromium" scheme="http://windrunnerlihuan.com/tags/Chromium/"/>
    
      <category term="启动" scheme="http://windrunnerlihuan.com/tags/%E5%90%AF%E5%8A%A8/"/>
    
  </entry>
  
  <entry>
    <title>无题</title>
    <link href="http://windrunnerlihuan.com/2018/09/12/%E6%97%A0%E9%A2%98/"/>
    <id>http://windrunnerlihuan.com/2018/09/12/无题/</id>
    <published>2018-09-12T09:28:11.000Z</published>
    <updated>2019-01-06T07:22:12.082Z</updated>
    
    <content type="html">&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;告别魔都，来到杭州，内心没有一丝喜悦，更多的是惋惜和遗憾。&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;又到了迷茫时间&quot;&gt;&lt;a href=&quot;#又到了迷茫时间&quot; class=&quot;headerlink&quot; title=&quot;又到了迷茫时间&quot;&gt;&lt;/a&gt;又到了迷茫时间&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;只身来到杭州，带着一脸不情愿。也许是在大上海呆久了，不喜欢杭州加班成风的氛围，和小家碧玉的格局。论资源，的确上海更胜一筹，体现在方方面面，难怪全国各地的人才都争相流入。很多人说这城市像围城，外面的人想进去，里面的人想出来。但更多的是外面的人进去了，就不想出来了，后来年龄大了，拼不过年轻人了，才不得不出去。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;说起来这次工作变更挺悲催的，进了杭州有名的血汗工厂。。。。。。如果996对于上海来说是深恶痛绝的，那么这儿有可能007都是理所当然。我也时常安慰自己，既来之，则安之。但是在时间安排上面还是很难适应，需要一段时间去消化。&lt;/p&gt;
&lt;h1 id=&quot;艰难的旅程&quot;&gt;&lt;a href=&quot;#艰难的旅程&quot; class=&quot;headerlink&quot; title=&quot;艰难的旅程&quot;&gt;&lt;/a&gt;艰难的旅程&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;可能很多人都有感触，应用开发到了一定年头就会出现瓶颈，这时候就面临转型问题。有的人坚持守住一亩三分地，有的人投入专项领域深入研究，也有的人走上层路线打入管理体系。或者遇到对的老大，一人得道，鸡犬升天。树大好乘凉，还有集团利益带来的阵阵凉风，从此一路起飞，直接实现各种自由。当然还有其它情况的，每个人都有不同境遇，结果也是形形色色。这是人生的重大抉择，也是职业难题。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;很多人跳不出自己的舒适区，也不愿跳出，毕竟在一个环境呆久了，人就会越来越懒，久而久之，就会形成习惯，很难接受改变。当然，我也是如此。但是有时候大家还是希望能够向内心向往的方向去转变，只是缺少机会。而主动转变的道路又十分艰难，要克服很多苦难，还要克服自己诸多缺点。这对人的意志也是极大的考验，因为稍微一懒惰，就会半途而废，即使偶尔坚持，也是一暴十寒，未见起色，效果微乎其微。&lt;/p&gt;
&lt;h1 id=&quot;无奈的抉择&quot;&gt;&lt;a href=&quot;#无奈的抉择&quot; class=&quot;headerlink&quot; title=&quot;无奈的抉择&quot;&gt;&lt;/a&gt;无奈的抉择&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我也承认自己是一条咸鱼，工作这么多年，什么也没有积累，倒是心态越来越佛系。多年来一直荣辱不惊，没有翻身的梦想，随遇而安。 小时候心很大，长大后心却很小。没有大目标，没有对物质追求的热衷，也没有对名利的追逐的欲望。唯有自己的一点小兴趣，希望能够长久保持。让生活也有一点色彩，不至于过的浑浑噩噩，换句话说，至少证明自己还活着，而不是行尸走肉。&lt;/p&gt;
&lt;h1 id=&quot;あの日見た花の名前を僕達はまだ知ら&quot;&gt;&lt;a href=&quot;#あの日見た花の名前を僕達はまだ知ら&quot; class=&quot;headerlink&quot; title=&quot;あの日見た花の名前を僕達はまだ知ら&quot;&gt;&lt;/a&gt;あの日見た花の名前を僕達はまだ知ら&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;罗嗦了这么多，也该列出今年未来计划了。目前看来，有如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Skia&lt;/li&gt;
&lt;li&gt;WebRTC&lt;/li&gt;
&lt;li&gt;Chromium&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;FFMpeg&lt;/li&gt;
&lt;li&gt;OpenGL&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;暂定就是这些，肯定学不完，但是也不能放弃呀。路漫漫其修远兮，贵在兴趣方向的坚持。总之就这样吧，期待自己有所改变。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/%E6%97%A0%E9%A2%98/mz.jpg&quot; alt=&quot;妹子&quot;&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;告别魔都，来到杭州，内心没有一丝喜悦，更多的是惋惜和遗憾。&lt;br&gt;
    
    </summary>
    
      <category term="日志" scheme="http://windrunnerlihuan.com/categories/%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="迷茫" scheme="http://windrunnerlihuan.com/tags/%E8%BF%B7%E8%8C%AB/"/>
    
  </entry>
  
  <entry>
    <title>PHOENIX</title>
    <link href="http://windrunnerlihuan.com/2018/07/24/PHOENIX/"/>
    <id>http://windrunnerlihuan.com/2018/07/24/PHOENIX/</id>
    <published>2018-07-24T09:02:11.000Z</published>
    <updated>2019-01-06T07:31:55.007Z</updated>
    
    <content type="html">&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这一拖就是半年，博客几乎要被废弃了。现在重新拾起，为这次归来起一个代号————————————————PHOENIX。&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;回顾&quot;&gt;&lt;a href=&quot;#回顾&quot; class=&quot;headerlink&quot; title=&quot;回顾&quot;&gt;&lt;/a&gt;回顾&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上一个系列是SurfaceFlinger，距离完结已经过去了半年（其实还有最后一篇关于Fence的内容，但是后来觉得，如果能够顺着这个系列一路踩下去，对于Fence的理解已经完全不用我再出一篇解析了，因此舍弃了续更的想法）。这半半，我的工作和生活发生了翻天覆地的变化。我一度认为已经超出了我个人的承受能力，但是事情来了，还是硬着头皮顶住了。一些事情也没有处理好，我也有反思过，主要还是因为自己责任心不够重。我也一直认为一个人是否成长，就看他的责任心有没有提升。但是提升责任心有一个最大的心里阻碍，就是懒(╯-╰)/众人皆懒，这个很难克服，必须养成良好的习惯才能慢慢改善。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;工作的事情真是一波三折，加入这家公司也是机缘巧合，名字就不透漏了。因为年后公司组织架构调整，人员有所变动，我也不例外。调整之后工作这半年，只能说是受尽心酸。博客停更半年先不说了，技术也一直停滞不前。忙的时候经常一天没喝一口水，或者就是早上刚去接了一杯水，晚上十点多下班后还没喝（＋﹏＋）。忙是一方面，另一方面是公司产品线决定的。因为这是一家纯业务公司，并且在集团快速发展的脚步下，部门也随之急剧变动，可想而知，就会有无休止的业务来折腾。但是却有一个致命的弊端，那就是技术积累严重不足。因为迫于集团的压力，平台老板也是卯足了劲的改革，大刀阔斧的进行业务更替，下面大小领导也是人心惶惶。因为经过几年折腾，平台的业绩本身已经在逐年下滑，但是又不能两耳不闻当咸鱼，所以才有了大小团队各种争相表现举动。产品的需求日日更迭先不提，技术团队也是为出成果各种邀功，因此，各个团队，海量的业务库，组件库，监控库，上报库……等等陆续诞生，先不管有么有用，或者是否已经有重复功能的库已，先集成给主应用再说，然后写个wiki，就证明我们组也有输出了，至少kpi有的写了。至于是否影响主应用性能，或者后续是否仍然使用，或者这个库的维护，这个就不是care的点了(一-一)。可以说，&lt;code&gt;有没有很重要，有没有用不重要&lt;/code&gt;。对外宣布这些组件库，感觉他们都说自己是这么个情况：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/PHOENIX/laoluo.gif&quot; alt=&quot;老罗&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;现在主应用已经越来越卡了，crash率也上升了许多，很多用户都投诉了，每天投诉邮件尽是批评和吐槽。用户数和活跃度也在下降，看着各种V的数据折线，仿佛看着A股的走势，的确有些心寒。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;因为是纯业务公司，再加上忙的不可开交，因此技术实力不进反退(ノ=Д=)ノ┻━┻这个有公司的原因，也有我的原因。本来我是想在音视频的道路上越走越长，顺路拾一拾图形图像的内容。可惜总是事与愿违啊，工作经历一波三折，一直在折腾，一直没有走到正向，反而越走越远。不过说到业务能力，在工作中也得到了锻炼，因为工作量很大，时间周期又很短，所以工作时候不能闷着头就是干，还要学会思考，比如提升工作效率，还有保证质量和复用性。我一直认为一个人的业务能力应该至少有两年时间去沉淀，具体沉淀的厚度就看个人理解程度了。但是总体来说，我还是觉得倒退了，这是无法回避的事实。&lt;/p&gt;
&lt;h1 id=&quot;展望&quot;&gt;&lt;a href=&quot;#展望&quot; class=&quot;headerlink&quot; title=&quot;展望&quot;&gt;&lt;/a&gt;展望&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上年提到，以后希望能够在音视频方向有所造诣。不求闻达于业界，但求沉浸于兴趣。因为在这家公司工作初期用到了OpenGL相关知识，因此闲暇之余写了个app——&lt;code&gt;狗头相机&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/PHOENIX/dogcamera.png&quot; alt=&quot;狗头相机&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;GitHub传送门如下：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/windrunnerlihuan/DogCamera&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;https://github.com/windrunnerlihuan/DogCamera&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;本来想做成抖音的效果，但是抖音的界面太花了，不利于功能的展示，所以UI设计就抄了VUE，但是会加上抖音的功能（&lt;strong&gt;因为工作实在太忙，因此很多功能还没有加上。目前已有拍摄、录制、加滤镜、混音等功能&lt;/strong&gt;）。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个app目前还有许多bug，以及很多功能还未添加，后续我都会慢慢完善。如果大家有好的点子，欢迎留言或者提issue～&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/PHOENIX/meizi.jpg&quot; alt=&quot;妹子图&quot;&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这一拖就是半年，博客几乎要被废弃了。现在重新拾起，为这次归来起一个代号————————————————PHOENIX。&lt;br&gt;
    
    </summary>
    
      <category term="日志" scheme="http://windrunnerlihuan.com/categories/%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="phoenix" scheme="http://windrunnerlihuan.com/tags/phoenix/"/>
    
  </entry>
  
  <entry>
    <title>Android SurfaceFlinger 学习之路(十二)----合成Layer</title>
    <link href="http://windrunnerlihuan.com/2018/01/09/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%8D%81%E4%BA%8C-%E5%90%88%E6%88%90Layer/"/>
    <id>http://windrunnerlihuan.com/2018/01/09/Android-SurfaceFlinger-学习之路-十二-合成Layer/</id>
    <published>2018-01-09T09:28:11.000Z</published>
    <updated>2019-01-06T07:29:47.192Z</updated>
    
    <content type="html">&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;脱更许久，慢慢步入咸鱼阶段。虽非我愿，但事事不如愿。一切尽在不言中，可与言者无一二。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上一节讲了合成Layer之前的准备工作，主要是就算可视化区域和初始化硬件合成环境，本节就讲讲最后的内容，合成Layer。&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;回顾&quot;&gt;&lt;a href=&quot;#回顾&quot; class=&quot;headerlink&quot; title=&quot;回顾&quot;&gt;&lt;/a&gt;回顾&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上一节讲合成的时候说过，合成分为两种，离线合成和在线合成：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;先将所有图层画到一个最终层（FrameBuffer）上，再将FrameBuffer送到LCD显示。由于合成FrameBuffer与送LCD显示一般是异步的（线下生成FrameBuffer，需要时线上的LCD去取），因此叫离线合成。&lt;/li&gt;
&lt;li&gt;不使用FrameBuffer，在LCD需要显示某一行的像素时，用显示控制器将所有图层与该行相关的数据取出，合成一行像素送过去。只有一个图层时，又叫Overlay技术。&lt;br&gt;由于省去合成FrameBuffer时读图层，写FrameBuffer的步骤，大幅降低了内存传输量，减少了功耗，但这个需要硬件支持。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;决定Layer的合成方式是在HWC硬件部分决定的，一般上层看不到代码，不过有幸Intel、三星等等开源了一部分我们还能窥一窥源码。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%E4%BA%8C%29----%E5%90%88%E6%88%90Layer/offline.jpg&quot; alt=&quot;offline&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果是Overlay的图层，直接交给显示器硬件系统去在线合成；如果是FRAME_BUFFER类型的图层，需要经过OpenGL处理，然后交给FrameBuffer送给显示器。&lt;/p&gt;
&lt;h1 id=&quot;合成流程&quot;&gt;&lt;a href=&quot;#合成流程&quot; class=&quot;headerlink&quot; title=&quot;合成流程&quot;&gt;&lt;/a&gt;合成流程&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们接着上一节的内容，SurfaceFlinger的handleMessageRefresh函数最后的内容。frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp，我们先来看看doComposition函数：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;void SurfaceFlinger::doComposition() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //将mRepaintEverything置为0，不用重绘所有区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const bool repaintEverything = android_atomic_and(0, &amp;amp;mRepaintEverything);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //遍历所有的DisplayDevice然后调用doDisplayComposition函数&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    for (size_t dpy=0 ; dpy&amp;lt;mDisplays.size() ; dpy++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const sp&amp;lt;DisplayDevice&amp;gt;&amp;amp; hw(mDisplays[dpy]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (hw-&amp;gt;isDisplayOn()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // transform the dirty region into this screen&#39;s coordinate space&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //获得屏幕的脏区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const Region dirtyRegion(hw-&amp;gt;getDirtyRegion(repaintEverything));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //合成，重绘framebuffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // repaint the framebuffer (if needed)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            doDisplayComposition(hw, dirtyRegion);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //清除屏幕脏区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hw-&amp;gt;dirtyRegion.clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //判断系统是否支持软件部分更新&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hw-&amp;gt;flip(hw-&amp;gt;swapRegion);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //清除交换区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hw-&amp;gt;swapRegion.clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // inform the h/w that we&#39;re done compositing&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //通知hwc硬件合成结束&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        hw-&amp;gt;compositionComplete();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //主要是调用hwc硬件的set函数&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //此方法将完成各个图层的合成与显示，等效于EGL标准里面的eglSwapBuffers，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //不过eglSwapBuffers是对OpenGL标准/GPU有效，此方法是对硬件合成器有效&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    postFramebuffer();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上述代码流程每个模块功能也很清晰，分步骤就是如下：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）遍历所有的DisplayDevice然后调用合成相关函数；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）获取每一个屏幕的脏区域；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）最重要的一步：合成；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）清除交换区域和屏幕脏区域；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;5）通知hwc硬件合成结束；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;6）最后主要是调用hwc硬件的set函数。此方法将完成各个图层的合成与显示，等效于EGL标准里面的eglSwapBuffers，不过eglSwapBuffers是对OpenGL标准/GPU有效，此方法是对硬件合成器有效。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;其中核心的就是合成步骤。我们先看看其他几个模块：&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;获取每一个屏幕的脏区域。frameworks/native/services/surfaceflinger/DisplayDevice.cpp中的getDirtyRegion函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;Region DisplayDevice::getDirtyRegion(&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; repaintEverything) &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Region dirty;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (repaintEverything) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dirty.&lt;span class=&quot;built_in&quot;&gt;set&lt;/span&gt;(getBounds());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Transform&amp;amp; planeTransform(mGlobalTransform);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dirty = planeTransform.transform(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;-&amp;gt;dirtyRegion);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dirty.andSelf(getBounds());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; dirty;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果需要重绘所有内容，就讲脏区域设为整个屏幕（但事实我们的repaintEverything是0，所以不会）；如果不要重绘所有，先对脏区域作矩阵变换（如果屏幕有过几何变换的transform），然后用脏区域与上屏幕大小，求出脏区域在屏幕上大小。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;获取了屏幕的脏区域之后，就开始合成了。&lt;/p&gt;
&lt;h2 id=&quot;开始合成&quot;&gt;&lt;a href=&quot;#开始合成&quot; class=&quot;headerlink&quot; title=&quot;开始合成&quot;&gt;&lt;/a&gt;开始合成&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们继续查看doDisplayComposition函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::doDisplayComposition(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; DisplayDevice&amp;gt;&amp;amp; hw,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Region&amp;amp; inDirtyRegion)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// We only need to actually compose the display if:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// 1) It is being handled by hardware composer, which may need this to&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//    keep its virtual display state machine in sync, or&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// 2) There is work to be done (the dirty region isn&#39;t empty)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//以下两种情况我们需要去合成显示：&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//1）需要报保持虚拟显示屏和物理显示屏同步显示的情况；&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//2）SF需要去渲染的脏区域不为空。&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; isHwcDisplay = hw-&amp;gt;getHwcDisplayId() &amp;gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!isHwcDisplay &amp;amp;&amp;amp; inDirtyRegion.isEmpty()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//SF需要渲染的脏区域&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;Region &lt;span class=&quot;title&quot;&gt;dirtyRegion&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(inDirtyRegion)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// compute the invalid region&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//需要渲染到硬件帧缓冲区中去的脏区域的&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    hw-&amp;gt;swapRegion.orSelf(dirtyRegion);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags = hw-&amp;gt;getFlags();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//在这种情况下，系统在软件上支持部分区域更新功能，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//同样，这个部分被更新的区域必须要是一个矩形区域。&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (flags &amp;amp; DisplayDevice::SWAP_RECTANGLE) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// we can redraw only what&#39;s dirty, but since SWAP_RECTANGLE only&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// takes a rectangle, we must make sure to update that whole&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// rectangle in that case&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dirtyRegion.&lt;span class=&quot;built_in&quot;&gt;set&lt;/span&gt;(hw-&amp;gt;swapRegion.bounds());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//在这种情况下，系统在硬件上直接支持部分区域更新功能，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//不过，这个部分被更新的区域必须要是一个矩形区域。&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (flags &amp;amp; DisplayDevice::PARTIAL_UPDATES) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// We need to redraw the rectangle that will be updated&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// (pushed to the framebuffer).&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// This is needed because PARTIAL_UPDATES only takes one&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// rectangle instead of a region (see DisplayDevice::flip())&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            dirtyRegion.&lt;span class=&quot;built_in&quot;&gt;set&lt;/span&gt;(hw-&amp;gt;swapRegion.bounds());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//在这种情况下，系统不支持部分更新区域，这时候就需要更新整个屏幕的内容&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// we need to redraw everything (the whole screen)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            dirtyRegion.&lt;span class=&quot;built_in&quot;&gt;set&lt;/span&gt;(hw-&amp;gt;bounds());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hw-&amp;gt;swapRegion = dirtyRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果没有开启Daltonize辅助功能（高对比性文字/色彩校正/颜色反转）&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//并且没有颜色矩阵去混合&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (CC_LIKELY(!mDaltonize &amp;amp;&amp;amp; !mHasColorMatrix)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//合成&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!doComposeSurfaces(hw, dirtyRegion)) &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;span class=&quot;comment&quot;&gt;//需要处理一下高对比性文字/色彩校正/颜色反转功能&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        RenderEngine&amp;amp; engine(getRenderEngine());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mat4 colorMatrix = mColorMatrix;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mDaltonize) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            colorMatrix = colorMatrix * mDaltonizer();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        engine.beginGroup(colorMatrix);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        doComposeSurfaces(hw, dirtyRegion);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        engine.endGroup();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// update the swap region and clear the dirty region&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//更新与framebuffer交换的脏区域，并清除应用脏区域&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    hw-&amp;gt;swapRegion.orSelf(dirtyRegion);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// swap buffers (presentation)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//与fb交换脏区域，会调用eglSwapBuffer函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//使用egl将egl中的合成好的图像，输出到DisplayDevice的mSurface中 &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    hw-&amp;gt;swapBuffers(getHwComposer());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; DisplayDevice类的成员变量swapRegion用来描述SurfaceFlinger服务需要渲染到硬件帧缓冲区中去的脏区域的。前面提到，inDirtyRegion也是用来描述SurfaceFlinger服务需要渲染的脏区域的，不过，它的作用是用来合成系统中各个应用程序窗口的图形缓冲区的，也就是说，当系统中各个应用程序窗口的图形缓冲区被合成之后，这个成员变量所描述的区域就会被清空，swapRegion会一直等到它的内容被渲染到硬件帧缓冲区中去之后，才会被清空。这样就可能会出现这种情况：上一次合成的图形缓冲区还未被渲染到硬件帧缓冲区中去，SurfaceFlinger服务又会执行新一轮的系统中各个应用程序窗口的图形缓冲区的合并操作。在这种情况下，SurfaceFlinger服务就需要将前面两次需要渲染到硬件帧缓冲区中去的区域合并在一起，以便可以正确地反映被刷新的UI。因此，函数在开头的地方，inDirtyRegion所描述的区域组合到成员变量swapRegion所描述的区域中去。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; 函数接下来调用用来描述系统主显示屏的一个DisplayDevice对象hw的成员函数getFlags来获得系统所支持的渲染方式，并且保存在一个uint32_t变量flags中。接下来，我们就分三种情况来讨论系统所支持的渲染方式：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;变量flags的DisplayDevice::SWAP_RECTANGLE位等于1。在这种情况下，系统在软件上支持部分区域更新功能，同样，这个部分被更新的区域必须要是一个矩形区域。&lt;/li&gt;
&lt;li&gt;变量flags的DisplayDevice::PARTIAL_UPDATES位等于1。在这种情况下，系统在硬件上直接支持部分区域更新功能，不过，这个部分被更新的区域必须要是一个矩形区域。&lt;/li&gt;
&lt;li&gt;变量flags的值等于0。在这种情况下，系统不支持部分更新区域，这时候就需要更新整个屏幕的内容。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; 在第1种和第2种情况中，由于被更新的区域都必须是一个矩形区域，因此，函数就需要变量inDirtyRegion所描述的一个区域设置为包含了所有脏区域的一个最小矩形区域。在第3种情况中，由于需要更新的是整个屏幕的内容，因此，函数就需要inDirtyRegion所描述的一个区域设置为等于屏幕大小的一个矩形区域。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;(在老的版本代码中，比如android2.3，部分更新还支持BUFFER_PRESERVED不规则区域更新。在保留后端图形缓冲区的内容的情况下，系统就可以支持仅仅渲染那些需要更新的脏区域，这些区域可以是不规则的。然而，实现不规则区域部分更新功能是有代价的，因为每次在渲染UI时，都要将后端图形缓冲区的内容拷贝回那些不在那些需要更新的区域中去，这会导致性能低下。因此，系统一般都不支持不规则区域部分更新功能。)&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; 在安卓L版本中，辅助设置中新加了3个功能，分别是高对比性文字，颜色反转，色彩校正。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This information applies only to devices running Android 5.0 and higher.&lt;/p&gt;
&lt;p&gt;High contrast makes text easier to read on your device. This feature fixes the text color as either black or white, depending on the original text color.&lt;/p&gt;
&lt;p&gt;To enable or disable high contrast text, follow these steps:&lt;br&gt;Go to Settings &amp;gt; Accessibility.&lt;br&gt;Select High contrast text.&lt;/p&gt;
&lt;p&gt;High-contrast text is currently an experimental feature, so it might not work correctly everywhere on your device.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; google说，这个功能就是让文字更容易阅读，也就是有点类似与文字高亮。最后的效果就是，把文字变成白色或黑色，把背景文字背景变成黑色或白色。也就是说，如果你之前的文字是白色，背景是黑色，就不会去应用这个功能。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果没有开启这个辅助功能，mDaltonize和mHasColorMatrix为null，那么直接调用doComposeSurfaces函数去合成图层；如果开启了辅助功能，那么就需要OpenGL引擎去处理颜色矩阵（高对比性文字主要是修改控件，颜色反转和颜色校正主要是通过操作gpu修改显示效果），这一部分有机会我们以后会研究研究。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;那么接下来两部就是合成图层和交换FrameBuffer了，我们逐步分析。&lt;/p&gt;
&lt;h1 id=&quot;合成图层&quot;&gt;&lt;a href=&quot;#合成图层&quot; class=&quot;headerlink&quot; title=&quot;合成图层&quot;&gt;&lt;/a&gt;合成图层&lt;/h1&gt;&lt;h2 id=&quot;doComposeSurfaces&quot;&gt;&lt;a href=&quot;#doComposeSurfaces&quot; class=&quot;headerlink&quot; title=&quot;doComposeSurfaces&quot;&gt;&lt;/a&gt;doComposeSurfaces&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;合成图层的函数是doComposeSurfaces，这个函数比较长，我们分段查看：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;bool SurfaceFlinger::doComposeSurfaces(const sp&amp;lt;const DisplayDevice&amp;gt;&amp;amp; hw, const Region&amp;amp; dirty)  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    RenderEngine&amp;amp; engine(getRenderEngine());  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const int32_t id = hw-&amp;gt;getHwcDisplayId();  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    HWComposer&amp;amp; hwc(getHwComposer());  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    HWComposer::LayerListIterator cur = hwc.begin(id);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const HWComposer::LayerListIterator end = hwc.end(id);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    bool hasGlesComposition = hwc.hasGlesComposition(id);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (hasGlesComposition) &amp;#123;//是否有egl合成  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //DisplayDevice类的成员函数makeCurrent的实现很简单，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //它只是通过调用函数eglMakeCurrent来将前面已经创建好的绘图表面以及绘图上下文设置为当前线程的绘图表面以及绘图上下文，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //即设置为SurfaceFlinger服务的UI渲染线程的绘图表面以及绘图上下文&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (!hw-&amp;gt;makeCurrent(mEGLDisplay, mEGLContext)) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ALOGW(&quot;DisplayDevice::makeCurrent failed. Aborting surface composition for display %s&quot;,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                  hw-&amp;gt;getDisplayName().string());  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //如果绑定失败了，就要取消设置OpenGL库在当前线程的绘图表面以及绘图上下文&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //那么就要去设置默认屏幕创建好的绘图表面和上下文为当前线程的内容&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if(!getDefaultDisplayDevice()-&amp;gt;makeCurrent(mEGLDisplay, mEGLContext)) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              ALOGE(&quot;DisplayDevice::makeCurrent on default display failed. Aborting.&quot;);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            return false;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // Never touch the framebuffer if we don&#39;t have any framebuffer layers  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const bool hasHwcComposition = hwc.hasHwcComposition(id);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (hasHwcComposition) &amp;#123;//是否有hwc合成  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // when using overlays, we assume a fully transparent framebuffer  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // NOTE: we could reduce how much we need to clear, for instance  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // remove where there are opaque FB layers. however, on some  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // GPUs doing a &quot;clean slate&quot; clear might be more efficient.  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // We&#39;ll revisit later if needed.  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //如果使用OverLay硬件合成，就要把FrameBuffer全都清除为透明色&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            engine.clearWithColor(0, 0, 0, 0);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; else &amp;#123;//是否有OpenGL合成&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //letterbox(信箱模式)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // we start with the whole screen area  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const Region bounds(hw-&amp;gt;getBounds());  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // we remove the scissor part  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // we&#39;re left with the letterbox region  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // (common case is that letterbox ends-up being empty) &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //移除内容区域，只留下大黑边（剪裁区域） &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const Region letterbox(bounds.subtract(hw-&amp;gt;getScissor()));  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // compute the area to clear  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //计算大黑边区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Region region(hw-&amp;gt;undefinedRegion.merge(letterbox));  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // but limit it to the dirty region  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //还要限制到更新的脏区域范围内&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            region.andSelf(dirty);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // screen is already cleared here  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //对大黑边进行挖洞处理，使用OpenGL填成黑色&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (!region.isEmpty()) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // can happen with SurfaceView  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //SurfaceView的实现原理就是打洞覆盖：另起一个图层（即新建一个Surface），&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //并把主图层的相应区域置为透明，然后渲染就发生在新图层中，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //最终显示效果自然是依赖SurfaceFlinger的叠加&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                drawWormhole(hw, region);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //如果不是主显屏&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (hw-&amp;gt;getDisplayType() != DisplayDevice::DISPLAY_PRIMARY) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // just to be on the safe side, we don&#39;t set the  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // scissor on the main display. It should never be needed  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // anyways (though in theory it could since the API allows it).  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //为了安全起见，这个操作不会在主显屏发生&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const Rect&amp;amp; bounds(hw-&amp;gt;getBounds());  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const Rect&amp;amp; scissor(hw-&amp;gt;getScissor());  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (scissor != bounds) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //如果剪裁区域和屏幕尺寸不匹配，就要清除所有塔之外的内容&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //并且enble GL剪裁器，在我们不需要绘制的地方不绘制任何内容&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // scissor doesn&#39;t match the screen&#39;s dimensions, so we  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // need to clear everything outside of it and enable  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // the GL scissor so we don&#39;t draw anything where we shouldn&#39;t  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // enable scissor for this frame  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                const uint32_t height = hw-&amp;gt;getHeight();  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                engine.setScissor(scissor.left, height - scissor.bottom,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        scissor.getWidth(), scissor.getHeight());  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;//...... &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这部分先调用hasGlesComposition函数和hasHwcComposition函数，就是看其对应的DisplayData中是否有hasFbComp和hasOvComp，对应有无OpenGL合成或者OverLay硬件合成。&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; HWComposer::hasGlesComposition(&lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; id) &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mHwc || &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;(id)&amp;gt;&lt;span class=&quot;number&quot;&gt;31&lt;/span&gt; || !mAllocatedDisplayIDs.hasBit(id))  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mDisplayData[id].hasFbComp;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; HWComposer::hasHwcComposition(&lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; id) &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mHwc || &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;(id)&amp;gt;&lt;span class=&quot;number&quot;&gt;31&lt;/span&gt; || !mAllocatedDisplayIDs.hasBit(id))  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mDisplayData[id].hasOvComp;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们在&lt;a href=&quot;http://windrunnerlihuan.com/2017/12/01/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%8D%81%E4%B8%80-%E5%90%88%E6%88%90Layer%E4%B9%8B%E5%87%86%E5%A4%87%E5%90%88%E6%88%90/&quot;&gt;Android SurfaceFlinger 学习之路(十一)—-合成Layer之准备合成&lt;/a&gt;中讲过，而这两个值是在prepare中调用Hwc的prepare函数之后赋值的，具体原理是在&lt;a href=&quot;http://windrunnerlihuan.com/2017/12/19/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%8D%81%E4%B8%80-PostView-%E9%99%84%EF%BC%9A%E7%A1%AC%E4%BB%B6HWC%E9%80%89%E5%8F%96%E5%90%88%E6%88%90%E7%B1%BB%E5%9E%8B%EF%BC%88Intel%EF%BC%89/&quot;&gt;Android SurfaceFlinger 学习之路(十一)(PostView)–附：硬件HWC选取合成类型（Intel）
&lt;/a&gt;中实现的，如果忘记了可以翻翻上一篇的内容。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果有OpenGL的合成，先调用DisplayDevice类的成员函数makeCurrent，通过调用函数eglMakeCurrent来将前面已经创建好的绘图表面以及绘图上下文设置为当前线程的绘图表面以及绘图上下文，即设置为SurfaceFlinger服务的UI渲染线程的绘图表面以及绘图上下文。如果绑定失败了，就要取消设置OpenGL库在当前线程的绘图表面以及绘图上下文。那么就要去设置默认屏幕创建好的绘图表面和上下文为当前线程的内容。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;因为合成有可能是混合合成，所以还要判断是否也有Overlay合成方式。如果有，就要把FrameBuffer全都清除为透明黑色。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果没有，就是OpenGL单独合成，就要使用&lt;code&gt;信箱模式&lt;/code&gt;。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个只是一种比喻，信箱模式可以查一查资料，比如&lt;a href=&quot;https://en.wikipedia.org/wiki/Letterboxing_(filming&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;维基百科&lt;/a&gt;)中的解释。我们这里理解为图层的宽高比大于电视的宽高比的情况。从名字来看，letterbox就像邮筒一样，中间是有内容的，上下是没用的。letterbox目标就是保存原有胶片的宽高比，使内容完整的展现在屏幕上。由于内容宽高比较大，所以上下会有黑屏。采用的技术就是：抽调部分扫描线，以满足宽高比，不利的结果就是图像质量下降。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以对于这种情况，我们需要对大黑边进行处理：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）移除内容区域，只留下大黑边（剪裁区域）；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）计算大黑边区域；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）还要限制到更新的脏区域范围内；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）对大黑边进行挖洞处理，使用OpenGL填成黑色&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceView的实现原理就是打洞覆盖：另起一个图层（即新建一个Surface），并把主图层的相应区域置为透明，然后渲染就发生在新图层中，最终显示效果自然是依赖SurfaceFlinger的叠加。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;最后就是一个特殊处理，对于不是主显屏（为了安全起见，这个操作不会在主显屏发生），如果剪裁区域和屏幕尺寸不匹配，就要清除所有塔之外的内容，并且enble GL剪裁器，在我们不需要绘制的地方不绘制任何内容。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;继续往下看：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    /*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * and then, render the layers targeted at the framebuffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const Vector&amp;lt; sp&amp;lt;Layer&amp;gt; &amp;gt;&amp;amp; layers(hw-&amp;gt;getVisibleLayersSortedByZ());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const size_t count = layers.size();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const Transform&amp;amp; tr = hw-&amp;gt;getTransform();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (cur != end) &amp;#123;//代表起码有两个以上图层  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // we&#39;re using h/w composer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        for (size_t i=0 ; i&amp;lt;count &amp;amp;&amp;amp; cur!=end ; ++i, ++cur) &amp;#123;//遍历图层 &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const sp&amp;lt;Layer&amp;gt;&amp;amp; layer(layers[i]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //clip用来描述要绘制的区域，而要绘制的区域即为当前需要指定的裁剪区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //就是全部图层的总体脏区域和这个图层的可视区域的交集&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const Region clip(dirty.intersect(tr.transform(layer-&amp;gt;visibleRegion)));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (!clip.isEmpty()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                switch (cur-&amp;gt;getCompositionType()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    //overlay不做处理&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    case HWC_CURSOR_OVERLAY:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    case HWC_OVERLAY: &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        const Layer::State&amp;amp; state(layer-&amp;gt;getDrawingState());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        if ((cur-&amp;gt;getHints() &amp;amp; HWC_HINT_CLEAR_FB)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                &amp;amp;&amp;amp; i&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                &amp;amp;&amp;amp; layer-&amp;gt;isOpaque(state) &amp;amp;&amp;amp; (state.alpha == 0xFF)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                &amp;amp;&amp;amp; hasGlesComposition) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            // never clear the very first layer since we&#39;re&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            // guaranteed the FB is already cleared&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            //上面说过，如果是Overlay合成，就要清除FrameBuffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            //这里以防万一，确保FB要被清除&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            layer-&amp;gt;clearWithOpenGL(hw, clip);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        break;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    //如果是OpenGL合成，就调用Layer的draw函数&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    case HWC_FRAMEBUFFER: &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        layer-&amp;gt;draw(hw, clip);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        break;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    //HWC_FRAMEBUFFER_TARGET是OpenGL合成后使用的目标层，直接就跳了&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    case HWC_FRAMEBUFFER_TARGET: &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        // this should not happen as the iterator shouldn&#39;t&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        // let us get there.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        ALOGW(&quot;HWC_FRAMEBUFFER_TARGET found in hwc list (index=%zu)&quot;, i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        break;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            layer-&amp;gt;setAcquireFence(hw, *cur);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; else &amp;#123;//只有一个或者没有图层  就直接使用OpenGL合成，调用Layer的draw&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // we&#39;re not using h/w composer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        for (size_t i=0 ; i&amp;lt;count ; ++i) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const sp&amp;lt;Layer&amp;gt;&amp;amp; layer(layers[i]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const Region clip(dirty.intersect(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    tr.transform(layer-&amp;gt;visibleRegion)));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (!clip.isEmpty()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                layer-&amp;gt;draw(hw, clip);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // disable scissor at the end of the frame&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    engine.disableScissor();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    return true;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这一段看注释就知道合成步骤。先根据z-order拿到所有的可视图层，然后分两种情况：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）起码有两个以上图层 ：遍历图层，用全部图层的总体脏区域和这个图层的可视区域求交集，计算出clip区域。如果clip区域不为空，根据Layer的合成类型分别进行处理：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;overlay不做处理，但是上面说过，如果是Overlay合成，就要清除FrameBuffer，这里以防万一，确保FB要被清除。&lt;/li&gt;
&lt;li&gt;如果是OpenGL合成，就调用Layer的draw函数。&lt;/li&gt;
&lt;li&gt;HWC_FRAMEBUFFER_TARGET是OpenGL合成后使用的目标层，直接就跳了。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）只有一个或者没有图层  就直接使用OpenGL合成，调用Layer的draw。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以合成主要是OpenGL处理，Layer的draw函数。&lt;/p&gt;
&lt;h2 id=&quot;OpenGL处理合成&quot;&gt;&lt;a href=&quot;#OpenGL处理合成&quot; class=&quot;headerlink&quot; title=&quot;OpenGL处理合成&quot;&gt;&lt;/a&gt;OpenGL处理合成&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们看看Layer的draw函数实现：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; Layer::draw(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; DisplayDevice&amp;gt;&amp;amp; hw, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Region&amp;amp; clip) &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    onDraw(hw, clip, &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;draw内部又调用了onDraw函数，这个函数有一点点小长，我们依然分段查看：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;void Layer::onDraw(const sp&amp;lt;const DisplayDevice&amp;gt;&amp;amp; hw, const Region&amp;amp; clip,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        bool useIdentityTransform) const&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //在纹理未创建好的情况下，一个应用程序窗口是不应该被渲染的&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (CC_UNLIKELY(mActiveBuffer == 0)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // the texture has not been created yet, this Layer has&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // in fact never been drawn into. This happens frequently with&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // SurfaceView because the WindowManager can&#39;t know when the client&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // has drawn the first time.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // If there is nothing under us, we paint the screen in black, otherwise&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // we just skip this update.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // figure out if there is something below us&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //在纹理未创建好的情况下，一个应用程序窗口是不应该被渲染的&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //这种情况频繁的发生在SurfaceView身上，因为WindowManger不知道它第一次绘制的时间&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //如果没有内容在它下面，我们把整个屏幕都画成黑色&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //否则就跳过这次更新&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //所以我们需要计算出在它下面的内容&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Region under;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const SurfaceFlinger::LayerVector&amp;amp; drawingLayers(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mFlinger-&amp;gt;mDrawingState.layersSortedByZ);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const size_t count = drawingLayers.size();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        for (size_t i=0 ; i&amp;lt;count ; ++i) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const sp&amp;lt;Layer&amp;gt;&amp;amp; layer(drawingLayers[i]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (layer.get() == static_cast&amp;lt;Layer const*&amp;gt;(this))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                break;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //这时候函数首先将位于当前正在处理的应用程序窗口下面的所有其它应用程序窗口的可见区域组合起来，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //并且保存在变量under所描述的区域中    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            under.orSelf( hw-&amp;gt;getTransform().transform(layer-&amp;gt;visibleRegion) );&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // if not everything below us is covered, we plug the holes!&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //由于这时候当前正在处理的应用程序窗口不会被绘制，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //因此，如果变量under所描述的区域小于参数clip所描述的区域，即变量holes所描述的区域不为空，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //那么SurfaceFlinger服务所要求缓制的区域clip就会留下一个洞&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Region holes(clip.subtract(under));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //这个洞会被绘制成黑色，这是通过调用函数clearWithOpenGL来实现的&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (!holes.isEmpty()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            clearWithOpenGL(hw, holes, 0, 0, 0, 1);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        return;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这段代码主要是用来处应用程序窗口的纹理尚未创建好的情况。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在纹理未创建好的情况下，一个应用程序窗口是不应该被渲染的。这时候函数首先将位于当前正在处理的应用程序窗口下面的所有其它应用程序窗口的可见区域组合起来，并且保存在变量under所描述的区域中。由于这时候当前正在处理的应用程序窗口不会被绘制，因此，如果变量under所描述的区域小于参数clip所描述的区域，即变量holes所描述的区域不为空，那么SurfaceFlinger服务所要求缓制的区域clip就会留下一个洞。这个洞会被绘制成黑色，这是通过调用函数clearWithOpenGL来实现的。绘制完成之后，函数就可以直接返回了。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里mActiveBuffer我们在&lt;a href=&quot;http://windrunnerlihuan.com/2017/11/09/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%8D%81-SurfaceFlinger%E5%A4%84%E7%90%86Layer%E6%9B%B4%E6%96%B0/&quot;&gt;Android SurfaceFlinger 学习之路(十)—-SurfaceFlinger处理Layer更新&lt;/a&gt;里面的更新纹理讲过，会为其赋值。&lt;/p&gt;
&lt;h2 id=&quot;绑定纹理&quot;&gt;&lt;a href=&quot;#绑定纹理&quot; class=&quot;headerlink&quot; title=&quot;绑定纹理&quot;&gt;&lt;/a&gt;绑定纹理&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接着看onDraw函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// Bind the current buffer to the GL texture, and wait for it to be&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// ready for us to draw into.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = mSurfaceFlingerConsumer-&amp;gt;bindTextureImage();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGW(&lt;span class=&quot;string&quot;&gt;&quot;onDraw: bindTextureImage failed (err=%d)&quot;&lt;/span&gt;, err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Go ahead and draw the buffer anyway; no matter what we do the screen&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// is probably going to have something visibly wrong.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这段代码首先，将buffer加入到GL texture，然后等待底层OpenGL调用GPU绘制完成纹理给我们上层返回。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们看看SurfaceFlingerConsumer的bindTextureImage函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; SurfaceFlingerConsumer::bindTextureImage()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; bindTextureImageLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;又调用了父类的GLConsumer的bindTextureImageLocked函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; GLConsumer::bindTextureImageLocked() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mEglDisplay == EGL_NO_DISPLAY) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;bindTextureImage: invalid display&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; INVALID_OPERATION;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GLint error;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; ((error = glGetError()) != GL_NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ST_LOGW(&lt;span class=&quot;string&quot;&gt;&quot;bindTextureImage: clearing GL error: %#04x&quot;&lt;/span&gt;, error);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//绑定一个Texture纹理，如果没有就创建&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glBindTexture(mTexTarget, mTexName);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT &amp;amp;&amp;amp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mCurrentTextureImage == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ST_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;bindTextureImage: no currently-bound texture&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_INIT;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//创建一个Image绘制&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = mCurrentTextureImage-&amp;gt;createIfNeeded(mEglDisplay,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                                        mCurrentCrop);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ST_LOGW(&lt;span class=&quot;string&quot;&gt;&quot;bindTextureImage: can&#39;t create image on display=%p slot=%d&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mEglDisplay, mCurrentTexture);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; UNKNOWN_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//将Image绑定到Texure&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentTextureImage-&amp;gt;bindToTextureTarget(mTexTarget);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// In the rare case that the display is terminated and then initialized&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// again, we can&#39;t detect that the display changed (it didn&#39;t), but the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// image is invalid. In this case, repeat the exact same steps while&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// forcing the creation of a new image.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((error = glGetError()) != GL_NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        glBindTexture(mTexTarget, mTexName);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = mCurrentTextureImage-&amp;gt;createIfNeeded(mEglDisplay,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                                            mCurrentCrop,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                                            &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ST_LOGW(&lt;span class=&quot;string&quot;&gt;&quot;bindTextureImage: can&#39;t create image on display=%p slot=%d&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    mEglDisplay, mCurrentTexture);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; UNKNOWN_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mCurrentTextureImage-&amp;gt;bindToTextureTarget(mTexTarget);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((error = glGetError()) != GL_NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ST_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;bindTextureImage: error binding external image: %#04x&quot;&lt;/span&gt;, error);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; UNKNOWN_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Wait for the new buffer to be ready.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//等待OpenGL处理完成，返回fence&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; doGLFenceWaitLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;OpenGL绑定纹理需要四步：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）绑定一个Texture纹理，如果没有就创建；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）创建一个Image用于绘制；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）将Image绑定到Texure；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）等待OpenGL处理完成，返回fence。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们依然分不查看：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）绑定纹理：glBindTexture。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里有一个特别尴尬的地方，就是我们这里的代码也看不到，因为这和GPU硬件相关，厂商不会开放这些代码的ToT。。。之前我们能看看高通、TI、甚至Intel的硬件模块代码实属运气，Google将其也放入了AOSP部分。但是对于GPU的源代码却看不到了，想想就明白了，现在显卡卖的一点都不比CPU便宜，尤其这两年人工智能、机器学习火起来，还有比特币的高涨，挖矿越来越猛烈，这些都需要超高速密集运算硬件支持，所以GPU价值和价格也有水涨船高之势头。所以指望这些厂商开发源代码实属异想天开=。=&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;虽然硬件代码看不到，但是我们可以曲线救国，从软件实现去分析功能。软件实现位于/frameworks/native/opengl/libagl/texture.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;glBindTexture&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(GLenum target, GLuint texture)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;ogles_context_t&lt;/span&gt;* c = &lt;span class=&quot;keyword&quot;&gt;ogles_context_t&lt;/span&gt;::get();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (target != GL_TEXTURE_2D &amp;amp;&amp;amp; target != GL_TEXTURE_EXTERNAL_OES) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ogles_error(c, GL_INVALID_ENUM);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Bind or create a texture&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//绑定或创建一个纹理&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;EGLTextureObject&amp;gt; tex;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (texture == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// 0 is our local texture object&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//0表示是本地的纹理对象&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        tex = c-&amp;gt;textures.defaultTexture;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        tex = c-&amp;gt;surfaceManager-&amp;gt;texture(texture);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ggl_unlikely(tex == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//创建一个纹理&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            tex = c-&amp;gt;surfaceManager-&amp;gt;createTexture(texture);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (tex == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ogles_error(c, GL_OUT_OF_MEMORY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    bindTextureTmu(c, c-&amp;gt;textures.active, texture, tex);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;bindTextureTmu&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;ogles_context_t&lt;/span&gt;* c, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; tmu, GLuint texture, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;EGLTextureObject&amp;gt;&amp;amp; tex)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (tex.get() == c-&amp;gt;textures.tmu[tmu].texture)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// free the reference to the previously bound object&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//释放对之前纹理对象的引用&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;texture_unit_t&lt;/span&gt;&amp;amp; u(c-&amp;gt;textures.tmu[tmu]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (u.texture)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        u.texture-&amp;gt;decStrong(c);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// bind this texture to the current active texture unit&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// and add a reference to this texture object&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//绑定这个纹理对象到当前活跃的纹理单元&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//并且增加引用计数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    u.texture = tex.get();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    u.texture-&amp;gt;incStrong(c);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    u.name = texture;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    invalidate_texture(c, tmu);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;invalidate_texture&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;ogles_context_t&lt;/span&gt;* c, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; tmu, &lt;span class=&quot;keyword&quot;&gt;uint8_t&lt;/span&gt; flags = &lt;span class=&quot;number&quot;&gt;0xFF&lt;/span&gt;)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    c-&amp;gt;textures.tmu[tmu].dirty = flags;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;软件实现也是先创建一个纹理texture对象，然后释放掉对之前纹理对象的引用，然后将引用指向新得纹理，再将引用计数加一，这样完成对当前纹理的绑定操作。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）创建一个Image用于绘制：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;mCurrentTextureImage是一个 EglImage，我们在&lt;a href=&quot;http://windrunnerlihuan.com/2017/11/09/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%8D%81-SurfaceFlinger%E5%A4%84%E7%90%86Layer%E6%9B%B4%E6%96%B0/&quot;&gt;Android SurfaceFlinger 学习之路(十)—-SurfaceFlinger处理Layer更新&lt;/a&gt;里面的更新纹理讲过，acquireBuffer时候会创建一个EglImage。所以这里调用EglImage的createIfNeeded函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; GLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                              &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Rect&amp;amp; cropRect,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                              &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; forceCreation) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// If there&#39;s an image and it&#39;s no longer valid, destroy it.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果之前的image不在有效了，就要销毁它&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; haveImage = mEglImage != EGL_NO_IMAGE_KHR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; displayInvalid = mEglDisplay != eglDisplay;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; cropInvalid = hasEglAndroidImageCrop() &amp;amp;&amp;amp; mCropRect != cropRect;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (haveImage &amp;amp;&amp;amp; (displayInvalid || cropInvalid || forceCreation)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!eglDestroyImageKHR(mEglDisplay, mEglImage)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;createIfNeeded: eglDestroyImageKHR failed&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mEglImage = EGL_NO_IMAGE_KHR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mEglDisplay = EGL_NO_DISPLAY;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// If there&#39;s no image, create one.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果没有image，就要创建一个&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mEglImage == EGL_NO_IMAGE_KHR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mEglDisplay = eglDisplay;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mCropRect = cropRect;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mEglImage = createImage(mEglDisplay, mGraphicBuffer, mCropRect);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Fail if we can&#39;t create a valid image.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//创建失败了，就只能GG了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mEglImage == EGL_NO_IMAGE_KHR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mEglDisplay = EGL_NO_DISPLAY;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mCropRect.makeInvalid();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;GraphicBuffer&amp;gt;&amp;amp; buffer = mGraphicBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;Failed to create image. size=%ux%u st=%u usage=0x%x fmt=%d&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            buffer-&amp;gt;getWidth(), buffer-&amp;gt;getHeight(), buffer-&amp;gt;getStride(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            buffer-&amp;gt;getUsage(), buffer-&amp;gt;getPixelFormat());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; UNKNOWN_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; OK;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果之前的image不在有效了，就要销毁它；如果没有image，就要创建一个；创建失败了，就只能GG了。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们可以继续看createImage函数，如何去创建一个image：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;EGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;GraphicBuffer&amp;gt;&amp;amp; graphicBuffer, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Rect&amp;amp; crop) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer-&amp;gt;getNativeBuffer();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLint attrs[] = &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        EGL_IMAGE_PRESERVED_KHR,        EGL_TRUE,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        EGL_IMAGE_CROP_LEFT_ANDROID,    crop.left,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        EGL_IMAGE_CROP_TOP_ANDROID,     crop.top,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        EGL_IMAGE_CROP_RIGHT_ANDROID,   crop.right,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        EGL_IMAGE_CROP_BOTTOM_ANDROID,  crop.bottom,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        EGL_NONE,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!crop.isValid()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// No crop rect to set, so terminate the attrib array before the crop.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        attrs[&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;] = EGL_NONE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!isEglImageCroppable(crop)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// The crop rect is not at the origin, so we can&#39;t set the crop on the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// EGLImage because that&#39;s not allowed by the EGL_ANDROID_image_crop&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// extension.  In the future we can add a layered extension that&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// removes this restriction if there is hardware that can support it.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        attrs[&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;] = EGL_NONE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*此句为创建Image的代码*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (image == EGL_NO_IMAGE_KHR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        EGLint error = eglGetError();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;error creating EGLImage: %#x&quot;&lt;/span&gt;, error);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; image;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面创建Image主要代码就是eglCreateImageKHR函数，不过依然很悲催，还是和GPU相关的硬件代码。我们只能继续曲线救国了，查看软件创建Image的实现，位于/frameworks/native/opengl/libagl/egl.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;EGLImageKHR &lt;span class=&quot;title&quot;&gt;eglCreateImageKHR&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(EGLDisplay dpy, EGLContext ctx, EGLenum target,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        EGLClientBuffer buffer, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; EGLint* &lt;span class=&quot;comment&quot;&gt;/*attrib_list*/&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;egl_display_t&lt;/span&gt;::is_valid(dpy) == EGL_FALSE) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ctx != EGL_NO_CONTEXT) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (target != EGL_NATIVE_BUFFER_ANDROID) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//这个buffer还是我们上层acquireBuffer时候获取的图形缓冲区buffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ANativeWindowBuffer* native_buffer = (ANativeWindowBuffer*)buffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (native_buffer-&amp;gt;common.magic != ANDROID_NATIVE_BUFFER_MAGIC)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (native_buffer-&amp;gt;common.version != &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(ANativeWindowBuffer))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt; (native_buffer-&amp;gt;format) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HAL_PIXEL_FORMAT_RGBA_8888:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HAL_PIXEL_FORMAT_RGBX_8888:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HAL_PIXEL_FORMAT_RGB_888:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HAL_PIXEL_FORMAT_RGB_565:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HAL_PIXEL_FORMAT_BGRA_8888:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;default&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    native_buffer-&amp;gt;common.incRef(&amp;amp;native_buffer-&amp;gt;common);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; (EGLImageKHR)native_buffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;说是创建一个EGLImageKHR，其实还是对我们上层acquireBuffer时候获取的图形缓冲区buffer，进行一些处理包装。因为这是软件实现，所以参考价值不大吧。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）将Image绑定到Texure：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; GLConsumer::EglImage::bindToTextureTarget(&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; texTarget) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glEGLImageTargetTexture2DOES(texTarget, (GLeglImageOES)mEglImage);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这次就真尴尬了，别说没硬件实现了，连软件都没得看了。。。。。。曲线救国没戏了，大清要亡啊。。。。。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;中华民国到来，学医救不了中国。。。。。。java救不了中国，但是php能=。=&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;沦落到看模拟器实现绑定，看看goldfish的实现，位于device/generic/goldfish/opengl/system/GLESv2/gl2.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//GL extensions&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;glEGLImageTargetTexture2DOES&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; * self, GLenum target, GLeglImageOES image)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    DBG(&lt;span class=&quot;string&quot;&gt;&quot;glEGLImageTargetTexture2DOES v2 target=%#x img=%p\n&quot;&lt;/span&gt;, target, image);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//&lt;span class=&quot;doctag&quot;&gt;TODO:&lt;/span&gt; check error - we don&#39;t have a way to set gl error&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;android_native_buffer_t&lt;/span&gt;* native_buffer = (&lt;span class=&quot;keyword&quot;&gt;android_native_buffer_t&lt;/span&gt;*)image;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (native_buffer-&amp;gt;common.magic != ANDROID_NATIVE_BUFFER_MAGIC) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (native_buffer-&amp;gt;common.version != &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(&lt;span class=&quot;keyword&quot;&gt;android_native_buffer_t&lt;/span&gt;)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GET_CONTEXT;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    DEFINE_AND_VALIDATE_HOST_CONNECTION();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//openGL的context上下文覆盖纹理坐标&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ctx-&amp;gt;override2DTextureTarget(target);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//然后用渲染引擎绑定Image的缓冲区引用&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    rcEnc-&amp;gt;rcBindTexture(rcEnc, ((&lt;span class=&quot;keyword&quot;&gt;cb_handle_t&lt;/span&gt; *)(native_buffer-&amp;gt;handle))-&amp;gt;hostHandle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//然后恢复纹理&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ctx-&amp;gt;restore2DTextureTarget();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;看代码核心也是三步：openGL的context上下文覆盖纹理坐标；然后用渲染引擎绑定Image的缓冲区引用；然后恢复纹理。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）等待OpenGL处理完成，返回fence：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上一节更新纹理时候讲过，里面调用acquireBufferLocked，buffer状态迁移到acquire，获得要显示出来的Buffer。这里会创建一个Fence，目前acquire fencefd还没使用，因为还未去合成这个layer，没到用layer中数据的时候。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果到了合成步骤，这个Fence才是使用的时机，就是接下来第四部做的操作：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// 等待生产者的acquire fence触发&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; GLConsumer::doGLFenceWaitLocked() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLDisplay dpy = eglGetCurrentDisplay();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLContext ctx = eglGetCurrentContext();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ST_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;doGLFenceWait: invalid current EGLDisplay&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; INVALID_OPERATION;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ST_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;doGLFenceWait: invalid current EGLContext&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; INVALID_OPERATION;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     &lt;span class=&quot;comment&quot;&gt;//等待生产者的acquire fence触发，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mCurrentFence-&amp;gt;isValid()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//检查EGL库是否支持EGL_ANDROID_native_fence_sync或者EGL_KHR_fence_sync属性的fence&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (SyncFeatures::getInstance().useWaitSync()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// Create an EGLSyncKHR from the current fence.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//dup一份上层传来的fence&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; fenceFd = mCurrentFence-&amp;gt;dup();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (fenceFd == &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ST_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;doGLFenceWait: error dup&#39;ing fence fd: %d&quot;&lt;/span&gt;, errno);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -errno;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            EGLint attribs[] = &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                EGL_NONE&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//创建一个GPU的fence&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            EGLSyncKHR sync = eglCreateSyncKHR(dpy,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (sync == EGL_NO_SYNC_KHR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                close(fenceFd);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ST_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;doGLFenceWait: error creating EGL fence: %#x&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        eglGetError());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; UNKNOWN_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;XXX:&lt;/span&gt; The spec draft is inconsistent as to whether this should&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// return an EGLint or void.  Ignore the return value for now, as&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// it&#39;s not strictly needed.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//GPU的fence等待，绘制完成会唤醒&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            eglWaitSyncKHR(dpy, sync, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            EGLint eglErr = eglGetError();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//唤醒后移除fence围栏&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            eglDestroySyncKHR(dpy, sync);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (eglErr != EGL_SUCCESS) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ST_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;doGLFenceWait: error waiting for EGL fence: %#x&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        eglErr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; UNKNOWN_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;span class=&quot;comment&quot;&gt;//不支持则上层fence去wait，一般都是-1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = mCurrentFence-&amp;gt;waitForever(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;string&quot;&gt;&quot;GLConsumer::doGLFenceWaitLocked&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ST_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;doGLFenceWait: error waiting for fence: %d&quot;&lt;/span&gt;, err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;等待逻辑步骤如下：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）这里会先等待生产者的acquire fence触发，检查这个Fence是否生效；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）然后查询EGL库是否支持EGL_ANDROID_native_fence_sync或者EGL_KHR_fence_sync属性的fence，这些都是从OpenGL相关的so库中获取，我们看看实现，位于frameworks/native/libs/gui/SyncFeatures.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;SyncFeatures::SyncFeatures() : Singleton&amp;lt;SyncFeatures&amp;gt;(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mHasNativeFenceSync(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mHasFenceSync(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mHasWaitSync(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// This can only be called after EGL has been initialized; otherwise the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// check below will abort.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt;* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    LOG_ALWAYS_FATAL_IF(exts == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&quot;eglQueryStringImplementationANDROID failed&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;built_in&quot;&gt;strstr&lt;/span&gt;(exts, &lt;span class=&quot;string&quot;&gt;&quot;EGL_ANDROID_native_fence_sync&quot;&lt;/span&gt;)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// This makes GLConsumer use the EGL_ANDROID_native_fence_sync&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// extension to create Android native fences to signal when all&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// GLES reads for a given buffer have completed.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mHasNativeFenceSync = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;built_in&quot;&gt;strstr&lt;/span&gt;(exts, &lt;span class=&quot;string&quot;&gt;&quot;EGL_KHR_fence_sync&quot;&lt;/span&gt;)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mHasFenceSync = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;built_in&quot;&gt;strstr&lt;/span&gt;(exts, &lt;span class=&quot;string&quot;&gt;&quot;EGL_KHR_wait_sync&quot;&lt;/span&gt;)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mHasWaitSync = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mString.append(&lt;span class=&quot;string&quot;&gt;&quot;[using:&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (useNativeFenceSync()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mString.append(&lt;span class=&quot;string&quot;&gt;&quot; EGL_ANDROID_native_fence_sync&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (useFenceSync()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mString.append(&lt;span class=&quot;string&quot;&gt;&quot; EGL_KHR_fence_sync&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (useWaitSync()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mString.append(&lt;span class=&quot;string&quot;&gt;&quot; EGL_KHR_wait_sync&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mString.append(&lt;span class=&quot;string&quot;&gt;&quot;]&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; SyncFeatures::useNativeFenceSync() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// EGL_ANDROID_native_fence_sync is not compatible with using the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// EGL_KHR_fence_sync extension for the same purpose.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mHasNativeFenceSync;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; SyncFeatures::useFenceSync() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;ifdef&lt;/span&gt; DONT_USE_FENCE_SYNC&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// on some devices it&#39;s better to not use EGL_KHR_fence_sync&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// even if they have it&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// currently we shall only attempt to use EGL_KHR_fence_sync if&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// USE_FENCE_SYNC is set in our makefile&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; !mHasNativeFenceSync &amp;amp;&amp;amp; mHasFenceSync;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; SyncFeatures::useWaitSync() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; (useNativeFenceSync() || useFenceSync()) &amp;amp;&amp;amp; mHasWaitSync;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;查询GPU相关属性在eglQueryStringImplementationANDROID函数，不过这次我们曲线救国都没用了，中华民国也GG了=。=想想也是，Fence实现每家GPU都不同，并且也算比较重要的技术，肯定不会给我们开放的。。。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）如果支持硬件Fence围栏，那么就用上层传入的fence去dup一份copy，然后根据这个copy创建一个GPU的fence。eglCreateSyncKHR依然GG，php也救不了中国～&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）GPU的fence等待，绘制完成会唤醒。等待操作GG。。。唤醒后就要销毁这个fence，放开栅栏；&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;5）fence的合法性验证为是否为-1，如果上层使用OpenGL绘制，那么fence就不为-1，下层也需要OpenGL绘制纹理；如果上层使用canvas绘制，那么fence就为-1，则gpu不等待，直接合成ok。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这就是OpenGL绑定纹理的操作，其中比较重要的是Fence在中间穿插的作用，这里只是简单分析，如果有机会，我会抽出一章专门分析一下。&lt;/p&gt;
&lt;h2 id=&quot;drawWithOpenGL&quot;&gt;&lt;a href=&quot;#drawWithOpenGL&quot; class=&quot;headerlink&quot; title=&quot;drawWithOpenGL&quot;&gt;&lt;/a&gt;drawWithOpenGL&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们继续回到Layer的onDraw函数，继续分析合成步骤。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;继续看下一部分：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;//这个Layer是否是受保护的，比如截屏的Layer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;bool blackOutLayer = isProtected() || (isSecure() &amp;amp;&amp;amp; !hw-&amp;gt;isSecure());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    RenderEngine&amp;amp; engine(mFlinger-&amp;gt;getRenderEngine());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //不是受保护的Layer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (!blackOutLayer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // TODO: we could be more subtle with isFixedSize()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //是否是规则的形状，或者上层应用程序有能力确认缓冲区的有效性&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //如果isFixedSize为true，那么就很容易处理图形的变换&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // Query the texture matrix given our current filtering mode.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        float textureMatrix[16];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSurfaceFlingerConsumer-&amp;gt;setFilteringEnabled(useFiltering);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSurfaceFlingerConsumer-&amp;gt;getTransformMatrix(textureMatrix);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //如果这个图形缓冲区之前曾经被旋转过，例如，被水平翻转或者垂直翻转过，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //那么在对它进行合并之前，还需要将它的旋转方向恢复回来&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (mSurfaceFlingerConsumer-&amp;gt;getTransformToDisplayInverse()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            /*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             * the code below applies the display&#39;s inverse transform to the texture transform&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             */&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // create a 4x4 transform matrix from the display transform flags&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const mat4 flipH(-1,0,0,0,  0,1,0,0, 0,0,1,0, 1,0,0,1);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const mat4 flipV( 1,0,0,0, 0,-1,0,0, 0,0,1,0, 0,1,0,1);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const mat4 rot90( 0,1,0,0, -1,0,0,0, 0,0,1,0, 1,0,0,1);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mat4 tr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            uint32_t transform = hw-&amp;gt;getOrientationTransform();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (transform &amp;amp; NATIVE_WINDOW_TRANSFORM_ROT_90)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                tr = tr * rot90;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (transform &amp;amp; NATIVE_WINDOW_TRANSFORM_FLIP_H)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                tr = tr * flipH;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (transform &amp;amp; NATIVE_WINDOW_TRANSFORM_FLIP_V)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                tr = tr * flipV;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // calculate the inverse&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //对它进行合并之前，还需要将它的旋转方向恢复回来&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //所以需要反转变换矩阵&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            tr = inverse(tr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // and finally apply it to the original texture matrix&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //然后将它应用到纹理中&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const mat4 texTransform(mat4(static_cast&amp;lt;const float*&amp;gt;(textureMatrix)) * tr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // Set things up for texturing.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //将上面对纹理的配置设置进来&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mTexture.setDimensions(mActiveBuffer-&amp;gt;getWidth(), mActiveBuffer-&amp;gt;getHeight());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mTexture.setFiltering(useFiltering);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mTexture.setMatrix(textureMatrix);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        engine.setupLayerTexturing(mTexture);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; else &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        engine.setupLayerBlackedOut();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们处理合成的Layer一般都是不受保护的Layer，如果是截屏或者其他被保护的Layer，blackOutLayer就为true。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里再说一下isFixedSize，这个在讲&lt;a href=&quot;http://windrunnerlihuan.com/2017/10/24/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B9%9D-SurfaceFlinger%E4%BA%8B%E5%8A%A1%E5%A4%84%E7%90%86/&quot;&gt;Android SurfaceFlinger 学习之路(九)—-SurfaceFlinger事务处理&lt;/a&gt;的时候提到过，我们再复习一下。&lt;br&gt; &amp;#160; &amp;#160; &amp;#160; &amp;#160;Layer类的成员变量mFixedSize是一个布尔变量，它的值可以通过Layer类的成员函数isFixedSize来获得。从前面&lt;a href=&quot;http://windrunnerlihuan.com/2017/06/17/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%85%AD-SurfaceFlinger%E5%88%9B%E5%BB%BASurface/&quot;&gt;Android SurfaceFlinger 学习之路(六)—-SurfaceFlinger创建Surface&lt;/a&gt;可以知道，当Android应用程序请求SurfaceFlinger服务分配一块图形缓冲区时，Android应用程序会传递两个参数reqWidth和reqHeight过来，表示请求分配的图形缓冲区的宽度和高度。这两个参数是可以同时等于0的，表示使用默认的宽度和高度值来创建所请求的图形缓冲区。这两个默认的宽度和高度值即等于当前所处理的应用程序窗口的宽度和高度值，而后者的宽度和高度值是在其创建的时候指定的。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Layer类的成员函数requestBuffer的参数reqWidth和reqHeight的值等于0意味着什么呢？从前面&lt;a href=&quot;http://windrunnerlihuan.com/2017/07/03/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%85%AB-Surface%E7%AE%A1%E7%90%86%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BA/&quot;&gt;Android SurfaceFlinger 学习之路(八)—-Surface管理图形缓冲区&lt;/a&gt;可以知道，Android应用程序在请求SurfaceFlinger服务分配一块图形缓冲区之前，会通过在Surface类内部来检查当前所处理的应用程序窗口的大小是否发生了变化。如果发生了变化，那么Android应用程序就会忽略掉缓存自己一侧的图形缓冲区，而去SurfaceFlinger服务请求新的图形缓冲区，因为那些缓存的图形缓冲区由于与它们所关联的应用程序窗口大小发生了变化而变为无效了。但是有一种特殊情况，在Android应用程序这一侧，用来描述应用程序窗口的Surface类可以不维护应用程序窗口的大小值。在这种情况下，Surface类就会将与它所关联的应用程序窗口的大小值设置为0，这意味着Android应用程序每次为这个应用程序窗口向SurfaceFlinger服务请求分配图形缓冲区之前，都认为这个应用程序窗口的大小值没有发生变化，同时传递给Layer类的参数reqWidth和reqHeight的值会等于0。事实上，一个应用程序窗口的大小是随时都可以发生变化的，比如，我们可以通过调用用来在Android应用程序和SurfaceFlinger服务建立连接的一个类型为Client的Binder对象的成员函数setState来改变一个应用程序窗口的大小，而一旦一个应用程序窗口的大小发生了变化，Layer类的成员函数doTransaction就会被调用。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Layer类的成员函数doTransaction在处理应用程序窗口大小变化时，需要考虑Android应用程序每次在为该应用程序窗口向SurfaceFlinger服务请求分配图形缓冲区之前，是否有能力去判断之前为该应用程序窗口缓存的图形缓冲区的有效性。如果没有的话，那么Layer类的成员函数doTransaction就需要将为该应用程序窗口缓存的图形缓冲区设置为无效，以便以后Android应用程序可以请求SurfaceFlinger服务分配新的、大小正确的图形缓冲区。从前面的分析还可以知道，当Android应用程序没有能力去判断之前为一个应用程序窗口所缓存的图形缓冲区的有效性时，那么之前在请求分配这些图形缓冲区时，传递给Layer类的的参数reqWidth和reqHeight的值就会等于0，这时候Layer类就会将Layer类的成员变量mFixedSize的值设置为false。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当Layer类的成员变量mFixedSize的值等于false时，由于Android应用程序没有能力去判断之前为一个应用程序窗口所缓存的图形缓冲区的有效性，因此，Layer类的成员函数doTransaction除了会调用外一个成员函数setBuffers来将新的应用程序窗口大小记录下来之外，还会通知BufferQueueProducer将当前正在处理的应用程序窗口所缓存的图形缓冲区设置为无效。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当Layer类的成员变量mFixedSize的值等于false时，Layer类的成员函数doTransaction还会提前将成员变量mCurrentState所描述的一个State对象的成员变量requested_w和requested_h的值保存到成员变量mDrawingState所描述的一个State对象的成员变量requested_w和requested_h中去，这是为了避免后面调用父类Layer的成员函数doTransaction时，会返回一个Layer::eVisibleRegion位不等于0的标志值给前面，而这将会导致SurfaceFlinger服务马上重新计算各个应用程序窗口的可见区域。现在不返回一个Layer::eVisibleRegion位不等于0的标志值给前面，就会等到下次渲染当前正在处理的应用程序窗口时再重新计算各个应用程序窗口的可见区域。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;太长了，跳过~&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;GLConsumer的构造函数中mFilteringEnabled(true)，所以filter为true。filter参数是OpenGL中使用纹理坐标映射到纹素数组，比如我们在doTransatin时候提到的线性滤波方法(linear filtering)。要理解这个也是需要OpenGL基础啊，奈何我也是小白=。=不过我们知道这里就是打开了滤波设置。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接下来代码用来检查当前正在处理的应用程序窗口的图形缓冲区是否是一个可以跳过合成阶段的图形缓冲区。本来这种图形缓冲区是可以直接渲染到硬件帧缓冲区中去的，但是由于它不是全屏显示的，因此就需要与其它应用程序窗口的图形缓冲区进行合并操作。如果这个图形缓冲区之前曾经被旋转过，例如，被水平翻转或者垂直翻转过，那么在对它进行合并之前，还需要将它的旋转方向恢复回来。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当用来描述一个图形缓冲区的一个GraphicBuffer对象的成员变量transform的值不等于0时，那么就说明这个图形缓冲区是被旋转过的，这时候函数就会对这个成员变量的值的NATIVE_WINDOW_TRANSFORM_FLIP_H位或者NATIVE_WINDOW_TRANSFORM_FLIP_V位进行取反，目的就是为了恢复它之前的旋转方向。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后进入最后一部分，drawWithOpenGL：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;drawWithOpenGL(hw, clip, useIdentityTransform);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;engine.disableTexturing();&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;drawWithOpenGL来将这个图形缓冲区的内容绘制在系统的主显示屏的指定区域上来，这个图形缓冲区的内容是使用mesh对象来描述的，包括顶点缓冲,索引缓冲,纹理对象等，而指定的主显示屏区域是由参数clip来描述的。&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;void Layer::drawWithOpenGL(const sp&amp;lt;const DisplayDevice&amp;gt;&amp;amp; hw,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const Region&amp;amp; /* clip */, bool useIdentityTransform) const &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const uint32_t fbHeight = hw-&amp;gt;getHeight();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const State&amp;amp; s(getDrawingState());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    computeGeometry(hw, mMesh, useIdentityTransform);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    /*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * NOTE: the way we compute the texture coordinates here produces&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * different results than when we take the HWC path -- in the later case&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * the &quot;source crop&quot; is rounded to texel boundaries.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * This can produce significantly different results when the texture&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * is scaled by a large amount.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     *&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * The GL code below is more logical (imho), and the difference with&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * HWC is due to a limitation of the HWC API to integers -- a question&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * is suspend is whether we should ignore this problem or revert to&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * GL composition when a buffer scaling is applied (maybe with some&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * minimal value)? Or, we could make GL behave like HWC -- but this feel&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * like more of a hack.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const Rect win(computeBounds());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    float left   = float(win.left)   / float(s.active.w);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    float top    = float(win.top)    / float(s.active.h);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    float right  = float(win.right)  / float(s.active.w);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    float bottom = float(win.bottom) / float(s.active.h);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // TODO: we probably want to generate the texture coords with the mesh&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // here we assume that we only have 4 vertices&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mesh::VertexArray&amp;lt;vec2&amp;gt; texCoords(mMesh.getTexCoordArray&amp;lt;vec2&amp;gt;());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    texCoords[0] = vec2(left, 1.0f - top);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    texCoords[1] = vec2(left, 1.0f - bottom);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    texCoords[2] = vec2(right, 1.0f - bottom);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    texCoords[3] = vec2(right, 1.0f - top);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    RenderEngine&amp;amp; engine(mFlinger-&amp;gt;getRenderEngine());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), s.alpha);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    engine.drawMesh(mMesh);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    engine.disableBlending();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个我们也是分步查看：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;    //主显示屏高度&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const uint32_t fbHeight = hw-&amp;gt;getHeight();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //当前正在处理的应用程序窗口状态的一个State对象s&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const State&amp;amp; s(getDrawingState());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    computeGeometry(hw, mMesh, useIdentityTransform);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;/*-----------------*/&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;void Layer::computeGeometry(const sp&amp;lt;const DisplayDevice&amp;gt;&amp;amp; hw, Mesh&amp;amp; mesh,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        bool useIdentityTransform) const&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const Layer::State&amp;amp; s(getDrawingState());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //上一步反转后的变换transform&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const Transform tr(useIdentityTransform ?&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hw-&amp;gt;getTransform() : hw-&amp;gt;getTransform() * s.transform);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const uint32_t hw_h = hw-&amp;gt;getHeight();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Rect win(s.active.w, s.active.h);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (!s.active.crop.isEmpty()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        win.intersect(s.active.crop, &amp;amp;win);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // subtract the transparent region and snap to the bounds&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //应用程序窗口减去透明区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    win = reduce(win, s.activeTransparentRegion);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //获取纹理的位置坐标&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mesh::VertexArray&amp;lt;vec2&amp;gt; position(mesh.getPositionArray&amp;lt;vec2&amp;gt;());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    position[0] = tr.transform(win.left,  win.top);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    position[1] = tr.transform(win.left,  win.bottom);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    position[2] = tr.transform(win.right, win.bottom);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    position[3] = tr.transform(win.right, win.top);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    for (size_t i=0 ; i&amp;lt;4 ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        position[i].y = hw_h - position[i].y;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这段代码首先得到主显示屏的高度fbHeight、要绘制的区域mesh的位置坐标，以及用来描述当前正在处理的应用程序窗口状态的一个State对象s。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接着往下看：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt; const Rect win(computeBounds());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    float left   = float(win.left)   / float(s.active.w);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    float top    = float(win.top)    / float(s.active.h);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    float right  = float(win.right)  / float(s.active.w);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    float bottom = float(win.bottom) / float(s.active.h);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // TODO: we probably want to generate the texture coords with the mesh&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // here we assume that we only have 4 vertices&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mesh::VertexArray&amp;lt;vec2&amp;gt; texCoords(mMesh.getTexCoordArray&amp;lt;vec2&amp;gt;());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    texCoords[0] = vec2(left, 1.0f - top);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    texCoords[1] = vec2(left, 1.0f - bottom);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    texCoords[2] = vec2(right, 1.0f - bottom);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    texCoords[3] = vec2(right, 1.0f - top);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;/*-----------------*/&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Rect Layer::computeBounds() const &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const Layer::State&amp;amp; s(getDrawingState());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Rect win(s.active.w, s.active.h);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (!s.active.crop.isEmpty()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        win.intersect(s.active.crop, &amp;amp;win);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // subtract the transparent region and snap to the bounds&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    return reduce(win, s.activeTransparentRegion);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面是根据mesh的位置计算出纹理顶点的坐标。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果Android应用程序没有指定一个窗口的纹理坐标，那么这个窗口的纹理坐标的默认值就使用要绘制的纹理的四个角的坐标来描述。注意，在计算纹理坐标的时候，还要考虑纹理的大小，以及纹理本身所设置的缩放因子，以便可以正确地将纹理绘制在应用程序窗口中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;继续往下，先看看这一步：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;RenderEngine&amp;amp; engine(mFlinger-&amp;gt;getRenderEngine());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), s.alpha);&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Android在此新增一个RenderEngine类，用来屏蔽OpenGL ES1.0、1.1和2.0的用法差异。基本用法和opengl是一样的，没有简化太多。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这一步是对颜色的处理，我们看看OpenGL E2.0的实现，位于frameworks/native/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; GLES20RenderEngine::setupDimLayerBlending(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; alpha) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mState.setPlaneAlpha(&lt;span class=&quot;number&quot;&gt;1.0f&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mState.setPremultipliedAlpha(&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mState.setOpaque(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mState.setColor(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, alpha/&lt;span class=&quot;number&quot;&gt;255.0f&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mState.disableTexture();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (alpha == &lt;span class=&quot;number&quot;&gt;0xFF&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        glDisable(GL_BLEND);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        glEnable(GL_BLEND);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里是设定图层混合的模式（mPremultipliedAlpha表示该图层是否已经做过预乘处理，Opaque表示该图层像素是否无视本图层的透明度，s.alpha表示该图层的整体透明度）。是否需要以混合模式来绘制，这是通过调用函数glEnable(GL_BLEND)来实现的。在需要混合模式来绘制纹理texture的情况下，还需要调用函数glBlendFunc来指定混合函数。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当前正在处理的应用程序窗口的Alpha通道的值小于0xFF，即State对象s的成员变量alpha的值小于0xFF，这表明该窗口的背景是半透明的。此时就需要使用混合模式来绘制纹理。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们看最后一部分：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;    engine.drawMesh(mMesh);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    engine.disableBlending();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/*---------GLES20RenderEngine.cpp---------*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; GLES20RenderEngine::drawMesh(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Mesh&amp;amp; mesh) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ProgramCache::getInstance().useProgram(mState);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//指定要绘制的顶点数组&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mesh.getTexCoordsSize()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        glEnableVertexAttribArray(Program::texCoords);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        glVertexAttribPointer(Program::texCoords,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mesh.getTexCoordsSize(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                GL_FLOAT, GL_FALSE,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mesh.getByteStride(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mesh.getTexCoords());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//指定要绘制的纹理坐标&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glVertexAttribPointer(Program::position,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mesh.getVertexSize(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            GL_FLOAT, GL_FALSE,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mesh.getByteStride(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mesh.getPositions());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//绘制前面指定的顶点数组以及纹理&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glDrawArrays(mesh.getPrimitive(), &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, mesh.getVertexCount());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mesh.getTexCoordsSize()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        glDisableVertexAttribArray(Program::texCoords);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; GLES20RenderEngine::disableBlending() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glDisable(GL_BLEND);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;分别调用函数glVertexPointer和glTexCoordPointer来指定要绘制的顶点数组以及纹理坐标。设置好要绘制的顶点数组以及纹理坐标之后，最后调用函数glDrawArrays来绘制前面指定的顶点数组以及纹理。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;其中这三个函数依然让我们曲线救国失败啊，大清彻底亡了=。=&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;doComposeSurfaces流程就分析完了，我们回到SF的doDisplayComposition函数继续。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;到此合成流程就完了，接下来到了和FB交换buffer。&lt;/p&gt;
&lt;h1 id=&quot;交换合成缓冲区&quot;&gt;&lt;a href=&quot;#交换合成缓冲区&quot; class=&quot;headerlink&quot; title=&quot;交换合成缓冲区&quot;&gt;&lt;/a&gt;交换合成缓冲区&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;沿着上面到了doDisplayComposition的最后一步。 与fb交换脏区域，会调用eglSwapBuffer函数，使用egl将egl中的合成好的图像，输出到DisplayDevice的mSurface中。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;继续查看，调用DisplayDevice的swapBuffers函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; DisplayDevice::swapBuffers(HWComposer&amp;amp; hwc) &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// We need to call eglSwapBuffers() if:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//  (1) we don&#39;t have a hardware composer, or&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//  (2) we did GLES composition this frame, and either&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//    (a) we have framebuffer target support (not present on legacy&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//        devices, where HWComposer::commit() handles things); or&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//    (b) this is a virtual display&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//当以下几种情况我们会调用eglSwapBuffers：&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//1.没有硬件合成器&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//2.使用OpenGL合成这一帧时候，以下两种情况之一&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//a.有FRAME_BUFFER_TARGET支持（overlay合成时候还有遗留的设备）&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//b.这是一个虚拟显屏&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hwc.initCheck() != NO_ERROR ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            (hwc.hasGlesComposition(mHwcDisplayId) &amp;amp;&amp;amp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             (hwc.supportsFramebufferTarget() || mType &amp;gt;= DISPLAY_VIRTUAL))) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//调用OpenGL库中的函数eglSwapBuffers来将系统的UI渲染到系统的主绘图表面上去的&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!success) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            EGLint error = eglGetError();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (error == EGL_CONTEXT_LOST ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    mType == DisplayDevice::DISPLAY_PRIMARY) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                LOG_ALWAYS_FATAL(&lt;span class=&quot;string&quot;&gt;&quot;eglSwapBuffers(%p, %p) failed with 0x%08x&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        mDisplay, mSurface, error);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;eglSwapBuffers(%p, %p) failed with 0x%08x&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        mDisplay, mSurface, error);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; result = mDisplaySurface-&amp;gt;advanceFrame();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (result != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;[%s] failed pushing new frame to HWC: %d&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mDisplayName.&lt;span class=&quot;built_in&quot;&gt;string&lt;/span&gt;(), result);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;调用OpenGL库中的函数eglSwapBuffers来将系统的UI渲染到系统的主绘图表面上去的，即渲染到系统的硬件帧缓冲区上去的。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里天不亡大清~~继续曲线救国，我们看看软件的实现，位于frameworks/native/opengl/libagl/egl.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;EGLBoolean &lt;span class=&quot;title&quot;&gt;eglSwapBuffers&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(EGLDisplay dpy, EGLSurface draw)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;egl_display_t&lt;/span&gt;::is_valid(dpy) == EGL_FALSE)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; setError(EGL_BAD_DISPLAY, EGL_FALSE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//将EGLSurface 强转为egl_surface_t结构体指针&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;egl_surface_t&lt;/span&gt;* d = &lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;egl_surface_t&lt;/span&gt;*&amp;gt;(draw);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!d-&amp;gt;isValid())&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; setError(EGL_BAD_SURFACE, EGL_FALSE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (d-&amp;gt;dpy != dpy)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; setError(EGL_BAD_DISPLAY, EGL_FALSE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// post the surface&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//然后调用swapBuffers完成交换操作&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    d-&amp;gt;swapBuffers();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// if it&#39;s bound to a context, update the buffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (d-&amp;gt;ctx != EGL_NO_CONTEXT) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        d-&amp;gt;bindDrawSurface((&lt;span class=&quot;keyword&quot;&gt;ogles_context_t&lt;/span&gt;*)d-&amp;gt;ctx);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// if this surface is also the read surface of the context&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// it is bound to, make sure to update the read buffer as well.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// The EGL spec is a little unclear about this.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;egl_context_t&lt;/span&gt;* c = &lt;span class=&quot;keyword&quot;&gt;egl_context_t&lt;/span&gt;::context(d-&amp;gt;ctx);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (c-&amp;gt;read == draw) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            d-&amp;gt;bindReadSurface((&lt;span class=&quot;keyword&quot;&gt;ogles_context_t&lt;/span&gt;*)d-&amp;gt;ctx);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; EGL_TRUE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;先将将EGLSurface 强转为egl_surface_t结构体指针，这里为什么能强转，我们下面一个小节会讲到。接着调用swapBuffers无参函数完成交换。同样位于frameworks/native/opengl/libagl/egl.cpp下：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;96&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;97&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;98&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;99&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;100&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;101&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;102&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;103&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;104&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;105&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;106&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;EGLBoolean egl_window_surface_v2_t::swapBuffers()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (!buffer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        return setError(EGL_BAD_ACCESS, EGL_FALSE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    /*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * Handle eglSetSwapRectangleANDROID()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * We copyback from the front buffer &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     //如果合成区域的脏区域不为空&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (!dirtyRegion.isEmpty()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //首先通过andSelf（）函数，算出在buffer中的dirtyRegion的区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dirtyRegion.andSelf(Rect(buffer-&amp;gt;width, buffer-&amp;gt;height));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //如果上一次buffer不为空&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (previousBuffer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // This was const Region copyBack, but that causes an&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // internal compile error on simulator builds&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //然后调用subtract将oldDirtyRegion中去掉了dirtyRegion区域，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //然后见这块区域从previousBuffer拷贝到当前的buffer中。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            /*const*/ Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (!copyBack.isEmpty()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                void* prevBits;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                if (lock(previousBuffer, &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        GRALLOC_USAGE_SW_READ_OFTEN, &amp;amp;prevBits) == NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    // copy from previousBuffer to buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    copyBlt(buffer, bits, previousBuffer, prevBits, copyBack);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    unlock(previousBuffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //将新的脏区域赋值给oldDirtyRegion&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        oldDirtyRegion = dirtyRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //将少之前buffer的对gralloc的引用&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (previousBuffer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        previousBuffer-&amp;gt;common.decRef(&amp;amp;previousBuffer-&amp;gt;common); &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        previousBuffer = 0;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    unlock(buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //完成buffer内容的填充，然后将previousBuffer指向buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    previousBuffer = buffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //这里的nativeWindow是egl_window_surface_v2_t结构体的成员变量&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //是一个ANativeWindow*类型&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //在DisplayDevice构造函数里调用eglCreateWindowSurface创建egl_window_surface_v2_t实例时候，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //new了一个Surface传入的&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //这里还调用了Surface的queueBuffer函数&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //从之前将Surface管理缓冲区得知，这会回调consumer的onFrameAvailable函数&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //调用surface的queueBuffer，agl的实现fencefd输入为-1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //硬件平台不为-1，比如抓高通的log&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //肯定在前面先创建了fence同步对象，经过merge后肯定不再为-1了&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    nativeWindow-&amp;gt;queueBuffer(nativeWindow, buffer, -1);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    buffer = 0;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // dequeue a new buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    int fenceFd = -1;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //然后dequeue一个新的buffer，并等待fence&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ///第一次被申请的buffer slot。返回-1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //假设不是。有release fence，则会dup该fencefd&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (nativeWindow-&amp;gt;dequeueBuffer(nativeWindow, &amp;amp;buffer, &amp;amp;fenceFd) == NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;Fence&amp;gt; fence(new Fence(fenceFd));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //wait，等待release fence触发&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //如果fence超时，就把buffer cancel掉。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (fence-&amp;gt;wait(Fence::TIMEOUT_NEVER)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            nativeWindow-&amp;gt;cancelBuffer(nativeWindow, buffer, fenceFd);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            return setError(EGL_BAD_ALLOC, EGL_FALSE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // reallocate the depth-buffer if needed&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //按需重新计算buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if ((width != buffer-&amp;gt;width) || (height != buffer-&amp;gt;height)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // TODO: we probably should reset the swap rect here&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // if the window size has changed&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            width = buffer-&amp;gt;width;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            height = buffer-&amp;gt;height;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (depth.data) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                free(depth.data);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                depth.width   = width;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                depth.height  = height;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                depth.stride  = buffer-&amp;gt;stride;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                depth.data    = (GGLubyte*)malloc(depth.stride*depth.height*2);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                if (depth.data == 0) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    setError(EGL_BAD_ALLOC, EGL_FALSE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    return EGL_FALSE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // keep a reference on the buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        buffer-&amp;gt;common.incRef(&amp;amp;buffer-&amp;gt;common);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // finally pin the buffer down&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                GRALLOC_USAGE_SW_WRITE_OFTEN, &amp;amp;bits) != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ALOGE(&quot;eglSwapBuffers() failed to lock buffer %p (%ux%u)&quot;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    buffer, buffer-&amp;gt;width, buffer-&amp;gt;height);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            return setError(EGL_BAD_ACCESS, EGL_FALSE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // FIXME: we should make sure we&#39;re not accessing the buffer anymore&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; else &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        return setError(EGL_BAD_CURRENT_SURFACE, EGL_FALSE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    return EGL_TRUE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;软件实现大致如下：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）如果合成区域的脏区域不为空，首先通过andSelf（）函数，算出在buffer中的dirtyRegion的区域，然后调用subtract将oldDirtyRegion中去掉了dirtyRegion区域，然后见这块区域从previousBuffer拷贝到当前的buffer中。这一部分和我门之前讲&lt;a href=&quot;http://windrunnerlihuan.com/2017/07/03/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%85%AB-Surface%E7%AE%A1%E7%90%86%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BA/&quot;&gt;Android SurfaceFlinger 学习之路(八)—-Surface管理图形缓冲区&lt;/a&gt;中Surface申请图形缓冲区过程类似，也是没有变化的区域就用copyBlt拷贝像素。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）将新的脏区域赋值给oldDirtyRegion，将少之前buffer的对gralloc的引用（这个我们在讲&lt;a href=&quot;http://windrunnerlihuan.com/2017/03/12/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B8%80-Android%E5%9B%BE%E5%BD%A2%E6%98%BE%E7%A4%BA%E4%B9%8BHAL%E5%B1%82Gralloc%E6%A8%A1%E5%9D%97%E5%AE%9E%E7%8E%B0/&quot;&gt;Android SurfaceFlinger 学习之路(一)—-Android图形显示之HAL层Gralloc模块实现&lt;/a&gt;中提到过，这是C语言中的一种继承方式），完成buffer内容的填充，然后将previousBuffer指向buffer。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）接着调用调用nativeBuffer变量的queueBuffer。这里的nativeWindow是egl_window_surface_v2_t结构体的成员变量，是一个ANativeWindow*类型。在DisplayDevice构造函数里调用eglCreateWindowSurface创建egl_window_surface_v2_t实例时候，new了一个Surface传入的。之前&lt;a href=&quot;http://windrunnerlihuan.com/2017/06/17/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%85%AD-SurfaceFlinger%E5%88%9B%E5%BB%BASurface/&quot;&gt;Android SurfaceFlinger 学习之路(六)—-SurfaceFlinger创建Surface&lt;/a&gt;讲过，Surface间接继承与ANativeWindow。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从之前将Surface管理缓冲区得知，这会回调consumer的onFrameAvailable函数，后面会讲到，这会触发FrameBufferSurface的onFrameAvailable函数回调。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;调用surface的queueBuffer，agl的实现fencefd输入为-1。硬件平台不为-1，比如抓高通的log，肯定在前面先创建了fence同步对象，经过merge后肯定不再为-1了。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）Dequeue一块新的buffer，并wait，等待release fence触发。如果等待超时，就将buffer cancel掉。第一次被申请的buffer slot，返回-1。假设不是。有release fence，则会dup该fencefd。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;5）按需重新计算buffer。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;既然提到交换缓冲区，就是讲生产者的内容post到消费者去，所以我们应该关注nativeWindow的queueBuffer过程。在讲这一部分之前，我们要看看之前讲到的DisplayDevice和FrameBufferSurface关系，还要引入一点OpenGL相关的内容。&lt;/p&gt;
&lt;h2 id=&quot;OpenGL环境创建&quot;&gt;&lt;a href=&quot;#OpenGL环境创建&quot; class=&quot;headerlink&quot; title=&quot;OpenGL环境创建&quot;&gt;&lt;/a&gt;OpenGL环境创建&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;使用OpenGL标准，用GPU把图层画到统一的FrameBuffer上，然后送显。毫无疑问这是离线合成的一种。EGL标准下，OpenGL环境创建的一般流程如下图所示： &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%E4%BA%8C%29----%E5%90%88%E6%88%90Layer/opengl.png&quot; alt=&quot;opengl&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这部分工作在SurfaceFlinger::init函数完成，也即服务初起之时。我们在讲&lt;a href=&quot;http://windrunnerlihuan.com/2017/05/25/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%BA%94-VSync-%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/&quot;&gt;Android SurfaceFlinger 学习之路(五)—-VSync 工作原理&lt;/a&gt;时候提到过这一部分：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;// initialize EGL for the default display&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;eglInitialize(mEGLDisplay, NULL, NULL);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;//初始化硬件合成器（这个和3D合成无关）&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;mHwc = new HWComposer(this,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        *static_cast&amp;lt;HWComposer::EventHandler *&amp;gt;(this));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;//创建渲染引擎，主要是选择EGL配置，选择OpenGL版本，创建OpenGL上下文&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc-&amp;gt;getVisualID());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;// retrieve the EGL context that was selected/created&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;mEGLContext = mRenderEngine-&amp;gt;getEGLContext();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &quot;couldn&#39;t create EGLContext&quot;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;//创建OpenGL的渲染目标Surface&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;for (size_t i=0 ; i&amp;lt;DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // set-up the displays that are already connected&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (mHwc-&amp;gt;isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // All non-virtual displays are currently considered secure.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        bool isSecure = true;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        createBuiltinDisplayLocked(type);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        wp&amp;lt;IBinder&amp;gt; token = mBuiltinDisplays[i];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;IGraphicBufferProducer&amp;gt; producer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;IGraphicBufferConsumer&amp;gt; consumer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        BufferQueue::createBufferQueue(&amp;amp;producer, &amp;amp;consumer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                new GraphicBufferAlloc());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        /*创建窗口Surface所需要的window句柄，注意这里面window句柄是FramebufferSurface*/&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;FramebufferSurface&amp;gt; fbs = new FramebufferSurface(*mHwc, i,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                consumer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        int32_t hwcId = allocateHwcDisplayId(type);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        /*在构造函数中，调用 eglCreateSurface 创建了OpenGL渲染的目标Surface*/&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;DisplayDevice&amp;gt; hw = new DisplayDevice(this,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                type, hwcId, mHwc-&amp;gt;getFormat(hwcId), isSecure, token,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                fbs, producer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mRenderEngine-&amp;gt;getEGLConfig());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (i &amp;gt; DisplayDevice::DISPLAY_PRIMARY) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // FIXME: currently we don&#39;t get blank/unblank requests&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // for displays other than the main display, so we always&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // assume a connected display is unblanked.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ALOGD(&quot;marking display %zu as acquired/unblanked&quot;, i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hw-&amp;gt;setPowerMode(HWC_POWER_MODE_NORMAL);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mDisplays.add(token, hw);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;// make the GLContext current so that we can create textures when creating Layers&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;// (which may happens before we render something)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;/*绑定上下文和Surface，以便绘制，这一步在调用OpenGL的drawcall之前就可以，这里调一次貌似是没必要的*/&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;getDefaultDisplayDevice()-&amp;gt;makeCurrent(mEGLDisplay, mEGLContext);&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;对使用opengl合成的layer将合成结果放置到HWC_FRAMEBUFFER_TARGET layer中，然后再交给HWComposer处理。在surfaceflinger的init函数中，定义了HWC_FRAMEBUFFER_TARGET layer合成时相应的生成者和消费者，每一个display相应有一个DisplayDevice作为生产者(opengl合成数据)，而FramebufferSurface是相应的消费者(注意这个消费者仅仅是处理opengl合成相关的，overlay全然由HAL层的hwcomposer处理)。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;注意到，创建的窗口是FramebufferSurface。为了更直观的查看Surface创建流程，我们再把DisplayDevice构造函数贴出来：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;DisplayDevice::DisplayDevice(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;SurfaceFlinger&amp;gt;&amp;amp; flinger,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        DisplayType type,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; hwcId,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; isSecure,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; wp&amp;lt;IBinder&amp;gt;&amp;amp; displayToken,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;DisplaySurface&amp;gt;&amp;amp; displaySurface,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;IGraphicBufferProducer&amp;gt;&amp;amp; producer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        EGLConfig config)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    : mFlinger(flinger),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mType(type), mHwcDisplayId(hwcId),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mDisplayToken(displayToken),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mDisplaySurface(displaySurface),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mDisplay(EGL_NO_DISPLAY),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mSurface(EGL_NO_SURFACE),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mDisplayWidth(), mDisplayHeight(), mFormat(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mFlags(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mPageFlipCount(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mIsSecure(isSecure),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mSecureLayerVisible(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mScreenAcquired(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mLayerStack(NO_LAYER_STACK),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mOrientation()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//利用bq创建surface&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mNativeWindow = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Surface(producer, &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ANativeWindow* &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; window = mNativeWindow.get();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; format;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    window-&amp;gt;query(window, NATIVE_WINDOW_FORMAT, &amp;amp;format);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Make sure that composition can never be stalled by a virtual display&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// consumer that isn&#39;t processing buffers fast enough. We have to do this&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// in two places:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// * Here, in case the display is composed entirely by HWC.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//   window&#39;s swap interval in eglMakeCurrent, so they&#39;ll override the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//   interval we set here.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mType &amp;gt;= DisplayDevice::DISPLAY_VIRTUAL)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        window-&amp;gt;setSwapInterval(window, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * Create our display&#39;s surface&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// 利用EGL创建本地opengl环境，要用opengl 合成layer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLSurface surface;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLint w, h;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//调用eglCreateWindowSurface创建EGLSurface&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    surface = eglCreateWindowSurface(display, config, window, &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    eglQuerySurface(display, surface, EGL_WIDTH,  &amp;amp;mDisplayWidth);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    eglQuerySurface(display, surface, EGL_HEIGHT, &amp;amp;mDisplayHeight);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDisplay = display;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurface = surface;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFormat  = format;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mPageFlipCount = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mViewport.makeInvalid();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFrame.makeInvalid();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// virtual displays are always considered enabled&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mScreenAcquired = (mType &amp;gt;= DisplayDevice::DISPLAY_VIRTUAL);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Name the display.  The name will be replaced shortly if the display&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// was created with createDisplay().&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt; (mType) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; DISPLAY_PRIMARY:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mDisplayName = &lt;span class=&quot;string&quot;&gt;&quot;Built-in Screen&quot;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; DISPLAY_EXTERNAL:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mDisplayName = &lt;span class=&quot;string&quot;&gt;&quot;HDMI Screen&quot;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;default&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mDisplayName = &lt;span class=&quot;string&quot;&gt;&quot;Virtual Screen&quot;&lt;/span&gt;;    &lt;span class=&quot;comment&quot;&gt;// e.g. Overlay #n&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在DisplayDevice构造函数里，利用从SF的init 函数里传入的BufferQueueProducer构造了一个Surface，然后调用eglCreateWindowSurface创建EGLSurface。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们知道surface继承了RefBase，所以get()实际上RefBase提供的函数。返回了surface的对象引用。而surface继承了ANativeObjectBase模版，通过ANativeObjectBase模版，可以理解成surface类也继承了AnativeWindow和RefBase。那么surface.get()作为AnativeWindow的类型参数传递给CreateWindowSurface也就好理解咯。也就是window本质上就是surface。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;为了解决上面留下的迷惑，我们看看eglCreateWindowSurface的实现。依然需要曲线救国，看看软件实现，位于frameworks/native/opengl/libagl/egl.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;EGLSurface &lt;span class=&quot;title&quot;&gt;eglCreateWindowSurface&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(  EGLDisplay dpy, EGLConfig config,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                    NativeWindowType window,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; EGLint *attrib_list)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; createWindowSurface(dpy, config, window, attrib_list);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; EGLSurface &lt;span class=&quot;title&quot;&gt;createWindowSurface&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(EGLDisplay dpy, EGLConfig config,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        NativeWindowType window, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; EGLint* &lt;span class=&quot;comment&quot;&gt;/*attrib_list*/&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*------前面都是一些错误检查------*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;egl_display_t&lt;/span&gt;::is_valid(dpy) == EGL_FALSE)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (window == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; setError(EGL_BAD_MATCH, EGL_NO_SURFACE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLint surfaceType;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &amp;amp;surfaceType) == EGL_FALSE)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; EGL_FALSE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!(surfaceType &amp;amp; EGL_WINDOW_BIT))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; setError(EGL_BAD_MATCH, EGL_NO_SURFACE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;ANativeWindow*&amp;gt;(window)-&amp;gt;common.magic !=&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ANDROID_NATIVE_WINDOW_MAGIC) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLint configID;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &amp;amp;configID) == EGL_FALSE)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; EGL_FALSE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; depthFormat;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; pixelFormat;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; setError(EGL_BAD_MATCH, EGL_NO_SURFACE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;FIXME:&lt;/span&gt; we don&#39;t have access to the pixelFormat here just yet.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// (it&#39;s possible that the surface is not fully initialized)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// maybe this should be done after the page-flip&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//if (EGLint(info.format) != pixelFormat)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//    return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;egl_surface_t&lt;/span&gt;* surface;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//egl_surface_t的详细实现为egl_window_surface_v2_t&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    surface = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;egl_window_surface_v2_t&lt;/span&gt;(dpy, config, depthFormat,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;ANativeWindow*&amp;gt;(window));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!surface-&amp;gt;initCheck()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// there was a problem in the ctor, the error&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// flag has been set.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;delete&lt;/span&gt; surface;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        surface = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; surface;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;前面都是一些错误检测，最后面new了一个egl_window_surface_v2_t结构体实现，egl_surface_t的详细实现为egl_window_surface_v2_t。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们再看看这个结构体部分内容：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;egl_window_surface_v2_t&lt;/span&gt; : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;egl_surface_t&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;egl_window_surface_v2_t&lt;/span&gt;(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            EGLDisplay dpy, EGLConfig config,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; depthFormat,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ANativeWindow* window);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ~&lt;span class=&quot;keyword&quot;&gt;egl_window_surface_v2_t&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; lock(ANativeWindowBuffer* buf, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; usage, &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;** vaddr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; unlock(ANativeWindowBuffer* buf);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ANativeWindow*   nativeWindow;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ANativeWindowBuffer*   buffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ANativeWindowBuffer*   previousBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;*    module;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; width;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; height;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;* bits;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GGLFormat &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* pixelFormatTable;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;egl_window_surface_v2_t&lt;/span&gt;::&lt;span class=&quot;keyword&quot;&gt;egl_window_surface_v2_t&lt;/span&gt;(EGLDisplay dpy,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        EGLConfig config,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; depthFormat,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ANativeWindow* window)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    : &lt;span class=&quot;keyword&quot;&gt;egl_surface_t&lt;/span&gt;(dpy, config, depthFormat), &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    nativeWindow(window), buffer(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;), previousBuffer(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;), module(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    bits(&lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;hw_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* pModule;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &amp;amp;pModule);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    module = &lt;span class=&quot;keyword&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;*&amp;gt;(pModule);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    pixelFormatTable = gglGetPixelFormatTable();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// keep a reference on the window&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    nativeWindow-&amp;gt;common.incRef(&amp;amp;nativeWindow-&amp;gt;common);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    nativeWindow-&amp;gt;query(nativeWindow, NATIVE_WINDOW_WIDTH, &amp;amp;width);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    nativeWindow-&amp;gt;query(nativeWindow, NATIVE_WINDOW_HEIGHT, &amp;amp;height);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面提到了，这里的nativeWindow是egl_window_surface_v2_t结构体的成员变量，是一个ANativeWindow*类型。在DisplayDevice构造函数里调用eglCreateWindowSurface创建egl_window_surface_v2_t实例时候，new了一个Surface传入的。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后就是上面调用Surface的dequeueBuffer，忘了的话可以往上翻=。=&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;前面提到过。eglSwapBuffers会触发DisplayDevice这个producer去dequeue buffer和queue buffer。这里的opengl合成和上层的opengl画图相似，在queuebuffer中就会为该buffer设置一个acquire buffer，传递给消费者consumer。从SF的init函数中得知，创建的窗口是FramebufferSurface，这个FrameBufferSurface包了一个BufferQueueConsumer，就像我们在&lt;a href=&quot;http://windrunnerlihuan.com/2017/07/03/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%85%AB-Surface%E7%AE%A1%E7%90%86%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BA/&quot;&gt;Android SurfaceFlinger 学习之路(八)—-Surface管理图形缓冲区&lt;/a&gt;中讲到上层绘制通知SF消费时候的SurfaceFlingerConsumer类的功能一样。所以最后queue buffer会触发FramebufferSurface::onFrameAvailable()。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;FrameBufrerSurface的类图如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%E4%BA%8C%29----%E5%90%88%E6%88%90Layer/FrameBufferSurface.jpg&quot; alt=&quot;FrameBufferSurface&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们再看看FrameBufferSurface的构造函数，位于frameworks/native/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;ifndef&lt;/span&gt; NUM_FRAMEBUFFER_SURFACE_BUFFERS&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;define&lt;/span&gt; NUM_FRAMEBUFFER_SURFACE_BUFFERS (2)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;FramebufferSurface::FramebufferSurface(HWComposer&amp;amp; hwc, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; disp,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;IGraphicBufferConsumer&amp;gt;&amp;amp; consumer) :&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ConsumerBase(consumer),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDisplayType(disp),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentBufferSlot(&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentBuffer(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mHwc(hwc)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mName = &lt;span class=&quot;string&quot;&gt;&quot;FramebufferSurface&quot;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mConsumer-&amp;gt;setConsumerName(mName);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mConsumer-&amp;gt;setConsumerUsageBits(GRALLOC_USAGE_HW_FB |&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                       GRALLOC_USAGE_HW_RENDER |&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                       GRALLOC_USAGE_HW_COMPOSER);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mConsumer-&amp;gt;setDefaultBufferFormat(mHwc.getFormat(disp));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mConsumer-&amp;gt;setDefaultBufferSize(mHwc.getWidth(disp),  mHwc.getHeight(disp));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mConsumer-&amp;gt;setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们注意到mConsumer的setConsumerUsageBits函数中设置的标志位：GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER。从之前的&lt;a href=&quot;http://windrunnerlihuan.com/2017/07/03/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%85%AB-Surface%E7%AE%A1%E7%90%86%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BA/&quot;&gt;Android SurfaceFlinger 学习之路(八)—-Surface管理图形缓冲区&lt;/a&gt;讲过，如果是上层应用程序申请图形缓冲区，应用程序进程使用的图形缓冲区一般都是在匿名共享内存里面分配的，这个图形缓冲区填好数据之后，就会再交给SurfaceFlinger服务来合成到硬件帧缓冲区上去渲染。因此，从前面传过来给函数gralloc_alloc的参数usage的GRALLOC_USAGE_HW_FB位会被设置为0，以便可以在匿名共享内存中分配一个图形缓冲区。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;而这里使用的标志位不同，GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER，从之前&lt;a href=&quot;http://windrunnerlihuan.com/2017/03/12/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B8%80-Android%E5%9B%BE%E5%BD%A2%E6%98%BE%E7%A4%BA%E4%B9%8BHAL%E5%B1%82Gralloc%E6%A8%A1%E5%9D%97%E5%AE%9E%E7%8E%B0/&quot;&gt;Android SurfaceFlinger 学习之路(一)—-Android图形显示之HAL层Gralloc模块实现&lt;/a&gt;可以得知，FrameBufferSurface类使用的图形缓冲区是直接在硬件帧缓冲区分配的，并且它可以直接将这些图形缓冲区渲染到硬件帧缓冲区中去。要从硬件帧缓冲区中分配和渲染图形缓冲区，就必须要将HAL层中的Gralloc模块加载到当前的进程空间来，并且打开里面的gralloc设备和fb设备，其中，gralloc设备用来分配图形缓冲区，而fb设备用来渲染图形缓冲区。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;还有一个注意点就是consumer的setDefaultMaxBufferCount函数，设置大小为NUM_FRAMEBUFFER_SURFACE_BUFFERS，为2。硬件帧缓冲区能够提供的图形缓冲区的个数等于2，这意味着Android系统可以使用双缓冲区技术来渲染系统的UI。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里有个误区，上面说的双缓冲并不是指4.1之后的Triple Buffer。三缓冲是对于Producer这一侧的生产者来说，我们在Layer的onFirstRef函数中有设置过，在&lt;a href=&quot;http://windrunnerlihuan.com/2017/06/17/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%85%AD-SurfaceFlinger%E5%88%9B%E5%BB%BASurface/&quot;&gt;Android SurfaceFlinger 学习之路(六)—-SurfaceFlinger创建Surface&lt;/a&gt;中也分析过，回顾一下：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; Layer::onFirstRef() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Creates a custom BufferQueue for SurfaceFlingerConsumer to use&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;IGraphicBufferProducer&amp;gt; producer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;IGraphicBufferConsumer&amp;gt; consumer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//BufferQueue创建图形缓冲区管理成员，我们以后分析图形缓冲区管理会讲到&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BufferQueue::createBufferQueue(&amp;amp;producer, &amp;amp;consumer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//mProducer 不为空了，赋值&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mProducer = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; MonitoredProducer(producer, mFlinger);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//mSurfaceFlingerConsumer 不为空了，赋值&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; SurfaceFlingerConsumer(consumer, mTextureName);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//设置消费者相关设置&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer-&amp;gt;setConsumerUsageBits(getEffectiveUsage(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer-&amp;gt;setContentsChangedListener(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer-&amp;gt;setName(mName);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// TARGET_DISABLE_TRIPLE_BUFFERING为false，所以使用了三缓冲，project butter计划嘛&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;ifdef&lt;/span&gt; TARGET_DISABLE_TRIPLE_BUFFERING&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;warning&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&quot;disabling triple buffering&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer-&amp;gt;setDefaultMaxBufferCount(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;else&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer-&amp;gt;setDefaultMaxBufferCount(&lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//获取默认显示器&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; DisplayDevice&amp;gt; hw(mFlinger-&amp;gt;getDefaultDisplayDevice());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//更新显示图像方向&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    updateTransformHint(hw);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;根据“黄油计划”定义了三缓冲。因为Producer定义了三缓冲，为了避免junk现象，让屏幕始终有一块buffer拉去离屏渲染。所以在producer这一侧，一块给cpu调度，一块给gpu绘制，看看谁有空闲的送给显示屏。如果默认的cpu调度和gpu性能都没有问题，在一个vsync周期内都能完成各自工作，那么以前仅有两块buffer情况下都不会出问题，因为，等他们用完后，总会空出一块buffer送给显示屏。但是如果其中任何一个出了问题，占用时间周期超过了一个vsync，或者更严重，两个都拖堂了，那么显示屏就没有空闲buffer拉取了，就会有很严重的掉帧。所以从4.1之后又加了一块buffer在producer这一侧，保证出问题时候还有一块buffer送显屏幕，即使从时间周期的pipeline来看，就这一个出问题的帧多显示了一下，但是后续的都显示正常，虽然仅仅延时了一帧，但是整体不会像以前那样严重的连续掉下帧。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这就是triple buffer的简单概述，如果有机会，后面专门讲讲。如果我理解有问题，也欢迎大家指正。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;因为对于屏幕显示器来说，上层app和SF都是属于producer生产者，而自己display才是消费者。屏幕是双缓冲显示，一块back buffer作为离屏渲染，一块front buffer作为在线显示，然后用完了又回到后台拉去producer送显的内容作为离屏渲染，同时之前的back buffer交换到前台作为front buffer在线显示，这样周而复始不挺循环。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里扯的有点多，如果有误请轻喷，欢迎指出，我会在第一时间修改。&lt;/p&gt;
&lt;h2 id=&quot;触发渲染&quot;&gt;&lt;a href=&quot;#触发渲染&quot; class=&quot;headerlink&quot; title=&quot;触发渲染&quot;&gt;&lt;/a&gt;触发渲染&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;继续回到上面内容，由eglSwapBuffers触发queueBuffer，进而触发FramebufferSurface中的onFrameAvailable方法：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; FramebufferSurface::onFrameAvailable() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;GraphicBuffer&amp;gt; buf;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;Fence&amp;gt; acquireFence;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*acquireBuffer，取得一块生产完成（OpenGL合成好）的Buffer*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = nextBuffer(buf, acquireFence);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;error latching nnext FramebufferSurface buffer: %s (%d)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                strerror(-err), err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*最终调用 gralloc 模块中的 post方法，该此Buffer送显*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    err = mHwc.fbPost(mDisplayType, acquireFence, buf);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;error posting framebuffer: %d&quot;&lt;/span&gt;, err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们先看看nextBuffer函数，取得一块生产完成（OpenGL合成好）的Buffer。（由于surfaceflinger是用opengl合成HWC_FRAMEBUFFER_TARGET layer的，所以有可能“合成”这个生产还未完毕）：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; FramebufferSurface::nextBuffer(sp&amp;lt;GraphicBuffer&amp;gt;&amp;amp; outBuffer, sp&amp;lt;Fence&amp;gt;&amp;amp; outFence) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BufferQueue::BufferItem item;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//通过acquireBufferLocked获取BufferItem，其中的mBuf就是buffer了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//acquireBufferLocked由之前父类传入的BufferQueueConsumer调用&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = acquireBufferLocked(&amp;amp;item, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == BufferQueue::NO_BUFFER_AVAILABLE) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        outBuffer = mCurrentBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;error acquiring buffer: %s (%d)&quot;&lt;/span&gt;, strerror(-err), err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// If the BufferQueue has freed and reallocated a buffer in mCurrentSlot&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// then we may have acquired the slot we already own.  If we had released&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// our current buffer before we call acquireBuffer then that release call&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// would have returned STALE_BUFFER_SLOT, and we would have called&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// freeBufferLocked on that slot.  Because the buffer slot has already&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// been overwritten with the new buffer all we have to do is skip the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// releaseBuffer call and we should be in the same state we&#39;d be in if we&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// had released the old buffer first.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//把老的buffer先release掉，还给BufferQueue，release时肯定得加入个release fence&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果在acquireBuffer之前调用releaseBuffer，就会返回一个STALE_BUFFER_SLOT状态，就不得不调用freeBufferLocked释放掉那个过时的buffer回到slot中。&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//为了避免获老的buffer被新的buffer内容覆盖，就要先acquire新的buffer然后release旧的buffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT &amp;amp;&amp;amp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        item.mBuf != mCurrentBufferSlot) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Release the previous buffer.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        err = releaseBufferLocked(mCurrentBufferSlot, mCurrentBuffer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err &amp;lt; NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;error releasing buffer: %s (%d)&quot;&lt;/span&gt;, strerror(-err), err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentBufferSlot = item.mBuf;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    outFence = item.mFence;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    outBuffer = mCurrentBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;获取一块合成好的buffer，就是之前HWC_FRAMEBUFFER标志的所有layer合成到HWC_FRAMEBUFFER_TARGET这个图层（有可能还没有合成好）。通过acquireBufferLocked获取BufferItem，其中的mBuf就是buffer了，acquireBufferLocked由之前父类传入的BufferQueueConsumer调用。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后把老的buffer先release掉，还给BufferQueue，release时肯定得加入个release fence。如果在acquireBuffer之前调用releaseBuffer，就会返回一个STALE_BUFFER_SLOT状态，就不得不调用freeBufferLocked释放掉那个过时的buffer回到slot中。为了避免获老的buffer被新的buffer内容覆盖，就要先acquire新的buffer然后release旧的buffer。这个我们在&lt;a href=&quot;http://windrunnerlihuan.com/2017/11/09/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%8D%81-SurfaceFlinger%E5%A4%84%E7%90%86Layer%E6%9B%B4%E6%96%B0/&quot;&gt;Android SurfaceFlinger 学习之路(十)—-SurfaceFlinger处理Layer更新&lt;/a&gt;讲过。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;继续回到剩下的内容，最终调用 gralloc 模块中的 post方法，该此Buffer送显。这一部分可以参考&lt;a href=&quot;http://windrunnerlihuan.com/2017/03/12/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B8%80-Android%E5%9B%BE%E5%BD%A2%E6%98%BE%E7%A4%BA%E4%B9%8BHAL%E5%B1%82Gralloc%E6%A8%A1%E5%9D%97%E5%AE%9E%E7%8E%B0/&quot;&gt;Android SurfaceFlinger 学习之路(一)—-Android图形显示之HAL层Gralloc模块实现&lt;/a&gt;，其中的图形缓冲区的渲染过程模块。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;到这里万里长征终于快到尽头了，doDisplayComposition函数流程分析完了。合成和送显示差不多完成了，还剩下最后一点杂物。&lt;/p&gt;
&lt;h2 id=&quot;硬件模块渲染过程&quot;&gt;&lt;a href=&quot;#硬件模块渲染过程&quot; class=&quot;headerlink&quot; title=&quot;硬件模块渲染过程&quot;&gt;&lt;/a&gt;硬件模块渲染过程&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们回到SF的doComposition函数，查看剩下内容：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//清除屏幕脏区域&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hw-&amp;gt;dirtyRegion.clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//判断系统是否支持软件部分更新&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hw-&amp;gt;flip(hw-&amp;gt;swapRegion);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//清除交换区域&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hw-&amp;gt;swapRegion.clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// inform the h/w that we&#39;re done compositing&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//通知hwc硬件合成结束&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        hw-&amp;gt;compositionComplete();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//主要是调用hwc硬件的set函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//此方法将完成各个图层的合成与显示，等效于EGL标准里面的eglSwapBuffers，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//不过eglSwapBuffers是对OpenGL标准/GPU有效，此方法是对硬件合成器有效&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    postFramebuffer();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;主要就三个功能：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）判断系统是否支持软件部分更新；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）通知hwc硬件合成结束；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）调用hwc硬件的set函数，各个overlay图层的合成与显示。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;老规矩，分步骤分析：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）判断系统是否支持软件部分更新。调用了DisplayDevice的flip函数，参数时要交换的合成区域：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;void DisplayDevice::flip(const Region&amp;amp; dirty) const&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFlinger-&amp;gt;getRenderEngine().checkErrors();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLDisplay dpy = mDisplay;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLSurface surface = mSurface;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;#ifdef EGL_ANDROID_swap_rectangle&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (mFlags &amp;amp; SWAP_RECTANGLE) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const Region newDirty(dirty.intersect(bounds()));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const Rect b(newDirty.getBounds());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        eglSetSwapRectangleANDROID(dpy, surface,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                b.left, b.top, b.width(), b.height());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;#else&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    (void) dirty; // Eliminate unused parameter warning&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;#endif&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mPageFlipCount++;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这段代码主要用来检查系统的主绘图表面是否支持EGL_ANDROID_swap_rectangle扩展属性。如果支持的话，那么每次在调用函数eglSwapBuffers来渲染UI时，都会使用软件的方式来支持部分更新区域功能，即：先得到不在新脏区域里面的那部分旧脏区域的内容，然后再将得到的这部分旧脏区域的内容拷贝回到要渲染的新图形缓冲区中去，这要求每次在渲染UI时，都要将被渲染的图形缓冲区以及对应的脏区域保存下来。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数会首先判断系统的主绘图表面是否支持EGL_ANDROID_swap_rectangle扩展属性。如果支持EGL_ANDROID_swap_rectangle扩展属性，即DisplayDevice类的成员变量mFlags的SWAP_RECTANGLE位等于1，那么就需要调用函数eglSetSwapRectangleANDROID来设置要渲染的区域，以便在渲染UI时，可以通过软件的方式来支持部分更新。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;不过从上一段选择部分更新的内容来看，是直接在硬件上支持部分更新，因而性能会更好。这一段软件的eglSetSwapRectangleANDROID就不看了曲线救国了，大清亡就亡了=。=&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）通知hwc硬件合成结束。go on：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; DisplayDevice::compositionComplete() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mDisplaySurface-&amp;gt;compositionComplete();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;之前从SF的init函数和DisplayDevice的构造函数得知，mDisplaySurface是一个FrameBufferSurface对象，所以我们继续看看它的compositionComplete函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; FramebufferSurface::compositionComplete()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mHwc.fbCompositionComplete();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;它又调用了HWComposer的fbCompositionComplete函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; HWComposer::fbCompositionComplete() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果支持HWC硬件1.1版本，就不用通知任何消息&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mHwc &amp;amp;&amp;amp; hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//否则通知FrameBuffer驱动FrameBufferTarget合成结束&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mFbDev-&amp;gt;compositionComplete) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mFbDev-&amp;gt;compositionComplete(mFbDev);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; INVALID_OPERATION;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果支持HWC硬件1.1版本，就不用通知任何消息，否则通知FrameBuffer驱动FrameBufferTarget合成结束。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）调用hwc硬件的set函数，各个overlay图层的合成与显示。这一步是postFramebuffer函数内完成的，我们看看实现：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;void SurfaceFlinger::postFramebuffer()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const nsecs_t now = systemTime();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDebugInSwapBuffers = now;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    HWComposer&amp;amp; hwc(getHwComposer());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (hwc.initCheck() == NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (!hwc.supportsFramebufferTarget()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // EGL spec says:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //   &quot;surface must be bound to the calling thread&#39;s current context,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //    for the current rendering API.&quot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            getDefaultDisplayDevice()-&amp;gt;makeCurrent(mEGLDisplay, mEGLContext);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //调用HWComposer的commit函数&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        hwc.commit();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // make the default display current because the VirtualDisplayDevice code cannot&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // deal with dequeueBuffer() being called outside of the composition loop; however&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // the code below can call glFlush() which is allowed (and does in some case) call&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // dequeueBuffer().&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //为了虚拟显示屏做的规避&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    getDefaultDisplayDevice()-&amp;gt;makeCurrent(mEGLDisplay, mEGLContext);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    for (size_t dpy=0 ; dpy&amp;lt;mDisplays.size() ; dpy++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;const DisplayDevice&amp;gt; hw(mDisplays[dpy]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const Vector&amp;lt; sp&amp;lt;Layer&amp;gt; &amp;gt;&amp;amp; currentLayers(hw-&amp;gt;getVisibleLayersSortedByZ());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //完毕了framebuffertarget layer的swapbuffers。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        hw-&amp;gt;onSwapBuffersCompleted(hwc);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const size_t count = currentLayers.size();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        int32_t id = hw-&amp;gt;getHwcDisplayId();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (id &amp;gt;=0 &amp;amp;&amp;amp; hwc.initCheck() == NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            HWComposer::LayerListIterator cur = hwc.begin(id);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const HWComposer::LayerListIterator end = hwc.end(id);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            for (size_t i = 0; cur != end &amp;amp;&amp;amp; i &amp;lt; count; ++i, ++cur) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //最后回调每个Layer的onLayerDisplayed函数&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                currentLayers[i]-&amp;gt;onLayerDisplayed(hw, &amp;amp;*cur);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; else &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            for (size_t i = 0; i &amp;lt; count; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                currentLayers[i]-&amp;gt;onLayerDisplayed(hw, NULL);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mLastSwapBufferTime = systemTime() - now;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDebugInSwapBuffers = 0;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    uint32_t flipCount = getDefaultDisplayDevice()-&amp;gt;getPageFlipCount();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (flipCount % LOG_FRAME_STATS_PERIOD == 0) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        logFrameStats();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;也是三部操作：1）调用调用HWComposer的commit函数完成OverLay合成；2）完毕了framebuffertarget layer的swapbuffers；3）最后回调每个Layer的onLayerDisplayed函数。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们先看第一步：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; HWComposer::commit() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; err = NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mHwc) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// On version 1.0, the OpenGL ES target surface is communicated&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// by the (dpy, sur) fields and we are guaranteed to have only&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// a single display.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mLists[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]-&amp;gt;dpy = eglGetCurrentDisplay();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mLists[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]-&amp;gt;sur = eglGetCurrentSurface(EGL_DRAW);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i=VIRTUAL_DISPLAY_ID_BASE; i&amp;lt;mNumDisplays; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;function&quot;&gt;DisplayData&amp;amp; &lt;span class=&quot;title&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mDisplayData[i])&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (disp.outbufHandle) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mLists[i]-&amp;gt;outbuf = disp.outbufHandle;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mLists[i]-&amp;gt;outbufAcquireFenceFd =&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        disp.outbufAcquireFence-&amp;gt;dup();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//主要是调用hwc硬件的set函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//此方法将完成各个图层的合成与显示，等效于EGL标准里面的eglSwapBuffers，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//不过eglSwapBuffers是对OpenGL标准/GPU有效，此方法是对硬件合成器有效&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        err = mHwc-&amp;gt;&lt;span class=&quot;built_in&quot;&gt;set&lt;/span&gt;(mHwc, mNumDisplays, mLists);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; i&amp;lt;mNumDisplays ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;function&quot;&gt;DisplayData&amp;amp; &lt;span class=&quot;title&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mDisplayData[i])&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.lastDisplayFence = disp.lastRetireFence;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.lastRetireFence = Fence::NO_FENCE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;-&amp;gt;retireFenceFd != &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    disp.lastRetireFence = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Fence(disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;-&amp;gt;retireFenceFd);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;-&amp;gt;retireFenceFd = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;-&amp;gt;flags &amp;amp;= ~HWC_GEOMETRY_CHANGED;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt;)err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;主要是调用hwc硬件的set函数，此方法将完成各个图层的合成与显示，等效于EGL标准里面的eglSwapBuffers，不过eglSwapBuffers是对OpenGL标准/GPU有效，此方法是对硬件合成器有效。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;不过这是hwc硬件的实现，我们也看不到代码。感兴趣的同学可以搜一搜AOSP里qcom、boardcom、ti、intel、samsung等公司开源出来的实现。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;后两部都是和Fence相关，这里不是重点：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;第二步是完毕了framebuffertarget layer的swapbuffers，调用DisplayDevice的onSwapBuffersCompleted函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; DisplayDevice::onSwapBuffersCompleted(HWComposer&amp;amp; hwc) &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hwc.initCheck() == NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mDisplaySurface-&amp;gt;onFrameCommitted();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;依然调用FrameBufferSurface的onFrameCommitted函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; FramebufferSurface::onFrameCommitted() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;Fence&amp;gt; fence = mHwc.getAndResetReleaseFence(mDisplayType);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (fence-&amp;gt;isValid() &amp;amp;&amp;amp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = addReleaseFence(mCurrentBufferSlot,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mCurrentBuffer, fence);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE_IF(err, &lt;span class=&quot;string&quot;&gt;&quot;setReleaseFenceFd: failed to add the fence: %s (%d)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                strerror(-err), err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;sp&amp;lt;Fence&amp;gt; HWComposer::getAndResetReleaseFence(&lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; id) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;(id)&amp;gt;&lt;span class=&quot;number&quot;&gt;31&lt;/span&gt; || !mAllocatedDisplayIDs.hasBit(id))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; Fence::NO_FENCE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; fd = INVALID_OPERATION;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mHwc &amp;amp;&amp;amp; hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; DisplayData&amp;amp; &lt;span class=&quot;title&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mDisplayData[id])&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// 这里的disp.framebufferTarget-&amp;gt;releaseFenceFd应该就是底层hwcomposer设置的 &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (disp.framebufferTarget) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            fd = disp.framebufferTarget-&amp;gt;releaseFenceFd;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.framebufferTarget-&amp;gt;acquireFenceFd = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.framebufferTarget-&amp;gt;releaseFenceFd = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; fd &amp;gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ? &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Fence(fd) : Fence::NO_FENCE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;onFrameCommitted主要就是获取hwcomposer设置的release fence，然后设置到slot中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;第三部回调Layer的onLayerDisplayed函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; Layer::onLayerDisplayed(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; DisplayDevice&amp;gt;&amp;amp; hw,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        HWComposer::HWCLayerInterface* layer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (layer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//HWCLayerVersion1的onDisplayed函数，位于HWComposer.cpp中&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        layer-&amp;gt;onDisplayed();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//将fence设置到slot中&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSurfaceFlingerConsumer-&amp;gt;setReleaseFence(layer-&amp;gt;getAndResetReleaseFence());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/*----------- HWCLayerVersion1 ----------*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; sp&amp;lt;Fence&amp;gt; getAndResetReleaseFence() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//获取layer的releaseFenceFd&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; fd = getLayer()-&amp;gt;releaseFenceFd;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        getLayer()-&amp;gt;releaseFenceFd = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//new 一个Fence&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; fd &amp;gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ? &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Fence(fd) : Fence::NO_FENCE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;onDisplayed&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;hwc_region_t&lt;/span&gt;&amp;amp; visibleRegion = getLayer()-&amp;gt;visibleRegionScreen;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        SharedBuffer &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* sb = SharedBuffer::bufferFromData(visibleRegion.rects);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (sb) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sb-&amp;gt;release();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// not technically needed but safer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            visibleRegion.numRects = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            visibleRegion.rects = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        getLayer()-&amp;gt;acquireFenceFd = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;而对overlay相应的layer而言，前面仅仅设置了acquire fence，在hwcomposer HAL处理后肯定会给加入一个release fence，而这一部分代码我们看不到实现。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;到此硬件模块渲染过程就分析完了。SF的doComposition函数的流程就结束了。&lt;/p&gt;
&lt;h1 id=&quot;更新SW-Vsync误差&quot;&gt;&lt;a href=&quot;#更新SW-Vsync误差&quot; class=&quot;headerlink&quot; title=&quot;更新SW Vsync误差&quot;&gt;&lt;/a&gt;更新SW Vsync误差&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;最后一部分就是SF中handleMessageRefresh最后一部，postComposition。主要用于调试，调Layer的onPostComposition方法。我们看看实现：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::postComposition()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; LayerVector&amp;amp; &lt;span class=&quot;title&quot;&gt;layers&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mDrawingState.layersSortedByZ)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; count = layers.size();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; i&amp;lt;count ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//调Layer的onPostComposition方法&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        layers[i]-&amp;gt;onPostComposition();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// 通过 HWComposer 获得 Fence&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; HWComposer&amp;amp; hwc = getHwComposer();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;Fence&amp;gt; presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//注意，如果硬件vsync已经被打开了，那么fence是无效了，只有它在关闭的情况下，它才有效&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//矫正更新Vsync，是否打开或关闭vsync信号&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (presentFence-&amp;gt;isValid()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mPrimaryDispSync.addPresentFence(presentFence)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            enableHardwareVsync();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disableHardwareVsync(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (kIgnorePresentFences) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; DisplayDevice&amp;gt; hw(getDefaultDisplayDevice());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hw-&amp;gt;isDisplayOn()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            enableHardwareVsync();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//动画相关&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mAnimCompositionPending) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mAnimCompositionPending = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (presentFence-&amp;gt;isValid()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mAnimFrameTracker.setActualPresentFence(presentFence);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// The HWC doesn&#39;t support present fences, so use the refresh&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// timestamp instead.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mAnimFrameTracker.setActualPresentTime(presentTime);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mAnimFrameTracker.advanceFrame();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/*--------Layer.cpp--------*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; Layer::onPostComposition() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mFrameLatencyNeeded) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; desiredPresentTime = mSurfaceFlingerConsumer-&amp;gt;getTimestamp();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mFrameTracker.setDesiredPresentTime(desiredPresentTime);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;Fence&amp;gt; frameReadyFence = mSurfaceFlingerConsumer-&amp;gt;getCurrentFence();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (frameReadyFence-&amp;gt;isValid()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mFrameTracker.setFrameReadyFence(frameReadyFence);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// There was no fence for this frame, so assume that it was ready&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// to be presented at the desired present time.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mFrameTracker.setFrameReadyTime(desiredPresentTime);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; HWComposer&amp;amp; hwc = mFlinger-&amp;gt;getHwComposer();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;Fence&amp;gt; presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (presentFence-&amp;gt;isValid()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mFrameTracker.setActualPresentFence(presentFence);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// The HWC doesn&#39;t support present fences, so use the refresh&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// timestamp instead.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mFrameTracker.setActualPresentTime(presentTime);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mFrameTracker.advanceFrame();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mFrameLatencyNeeded = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;postComposition函数中比较重要的是更新SW Vsync的误差值。注意，如果硬件vsync已经被打开了，那么fence是无效了，只有它在关闭的情况下，它才有效。当更新SW Vsync模型后，就会关闭硬件Vsync信号，这时候Fence就有效了。所以我们进入第一个if条件内部，查看DispSync的addPresentFence函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; DispSync::addPresentFence(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;Fence&amp;gt;&amp;amp; fence) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   &lt;span class=&quot;comment&quot;&gt;// 将当前硬件vsync的fence保存在 mPresentFences里, 目的是为了计算偏移&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;// mPresentFences 最多保存8个硬件 偏移&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mPresentFences[mPresentSampleOffset] = fence;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mPresentTimes[mPresentSampleOffset] = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mPresentSampleOffset = (mPresentSampleOffset + &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;) % NUM_PRESENT_SAMPLES;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mNumResyncSamplesSincePresent = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; &lt;span class=&quot;comment&quot;&gt;// 将 mNumResyncSamplesSincePresent 置为0，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; NUM_PRESENT_SAMPLES; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;Fence&amp;gt;&amp;amp; f(mPresentFences[i]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (f != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;  &lt;span class=&quot;comment&quot;&gt;//这里 f 是有可能为NULL, 即只有一个 硬件 vsync 偏移时&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; t = f-&amp;gt;getSignalTime();  &lt;span class=&quot;comment&quot;&gt;//猜测这个就是硬件 vsync的时间&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (t &amp;lt; INT64_MAX) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mPresentFences[i].clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              &lt;span class=&quot;comment&quot;&gt;//将每个vsync时间戳记录在 mPresentTimes 里，这里 kPresentTimeOffset是可以配置的，即可调的&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mPresentTimes[i] = t + kPresentTimeOffset;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   &lt;span class=&quot;comment&quot;&gt;//更新错误信息&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    updateErrorLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// 这里，一般的情况是 mModelUpdated 已经被更新了，然后硬件vsync被disable了，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// 所以这里只需要看SW vsync的真实的硬件vsync的误差是否在可&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// 允许的范围内即可&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; !mModelUpdated || mError &amp;gt; kErrorThreshold;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;ddPresentFence最后的返回, mError是方差，见下面分析，当方差大于 kErrorThreshold后就返回true：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; DispSync::updateErrorLocked() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mModelUpdated) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Need to compare present fences against the un-adjusted refresh period,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// since they might arrive between two events.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//得到真实的 period, 具体见 5.2.4 updateModelLocked 里的分析&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; period = mPeriod / (&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt; + mRefreshSkipCount);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; numErrSamples = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; sqErrSum = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   &lt;span class=&quot;comment&quot;&gt;//这里的 mReferenceTime 是第一个硬件vsync的时间戳 见 addResyncSample里的 mReferenceTime&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; NUM_PRESENT_SAMPLES; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; sample = mPresentTimes[i] - mReferenceTime;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       &lt;span class=&quot;comment&quot;&gt;// 这里 sample 一般来说是大于偏移的&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (sample &amp;gt; mPhase) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; sampleErr = (sample - mPhase) % period;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (sampleErr &amp;gt; period / &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                sampleErr -= period;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//记录 偏移差的平方和&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sqErrSum += sampleErr * sampleErr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            numErrSamples++;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     &lt;span class=&quot;comment&quot;&gt;// 说到底mError就是方差&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (numErrSamples &amp;gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mError = sqErrSum / numErrSamples;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mError = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (kTraceDetailedInfo) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ATRACE_INT64(&lt;span class=&quot;string&quot;&gt;&quot;DispSync:Error&quot;&lt;/span&gt;, mError);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果 addPresentFence返回true, 那么就说明SW vsync和硬件Vsync的误差已经无法接受了，那么这时就得重新打开硬件Vsync，来重新调节SW vsync模型了。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;合成全部流程到此结束，打完收工~~&lt;/p&gt;
&lt;h1 id=&quot;小结&quot;&gt;&lt;a href=&quot;#小结&quot; class=&quot;headerlink&quot; title=&quot;小结&quot;&gt;&lt;/a&gt;小结&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;合成流程中比较重要的就是Layer与纹理，我们贴两幅图，一张是GraphicBuffer上传为纹理，一张为更新纹理：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%E4%BA%8C%29----%E5%90%88%E6%88%90Layer/image.jpg&quot; alt=&quot;image&quot;&gt;&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;GraphicBuffer上传为纹理&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%E4%BA%8C%29----%E5%90%88%E6%88%90Layer/flow.jpg&quot; alt=&quot;flow&quot;&gt;&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;更新纹理&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;合成流程是整个SurfaceFlinger中最重要的环节，这个大山我们推到之后，对于Android显示系统的理解豁然开朗。后面我们有机会继续研究研究其他内容，比如Fence相关的东西（可能没有时间=。=）&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;细数2017年每一件事，真是事事不如意。这一年，也是我整个人生中最动荡的一年，尝遍酸甜苦辣，受尽世态炎凉ToT~&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;希望2018年能对我好一点。。。。。。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%E4%BA%8C%29----%E5%90%88%E6%88%90Layer/meizi.jpg&quot; alt=&quot;meizi&quot;&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;脱更许久，慢慢步入咸鱼阶段。虽非我愿，但事事不如愿。一切尽在不言中，可与言者无一二。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上一节讲了合成Layer之前的准备工作，主要是就算可视化区域和初始化硬件合成环境，本节就讲讲最后的内容，合成Layer。&lt;br&gt;
    
    </summary>
    
      <category term="Android技术点" scheme="http://windrunnerlihuan.com/categories/Android%E6%8A%80%E6%9C%AF%E7%82%B9/"/>
    
    
      <category term="SurfaceFlinger" scheme="http://windrunnerlihuan.com/tags/SurfaceFlinger/"/>
    
  </entry>
  
  <entry>
    <title>Android SurfaceFlinger 学习之路(十一)(PostView)--附：硬件HWC选取合成类型（Intel）</title>
    <link href="http://windrunnerlihuan.com/2017/12/19/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%8D%81%E4%B8%80-PostView-%E9%99%84%EF%BC%9A%E7%A1%AC%E4%BB%B6HWC%E9%80%89%E5%8F%96%E5%90%88%E6%88%90%E7%B1%BB%E5%9E%8B%EF%BC%88Intel%EF%BC%89/"/>
    <id>http://windrunnerlihuan.com/2017/12/19/Android-SurfaceFlinger-学习之路-十一-PostView-附：硬件HWC选取合成类型（Intel）/</id>
    <published>2017-12-19T10:31:11.000Z</published>
    <updated>2019-01-06T07:29:39.427Z</updated>
    
    <content type="html">&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里说点题外话，高通最近势头正猛啊，回拒了博通的恶意收购，又出了骁龙835进军PC市场，拉着AMD一起干英特尔。英特尔在移动设备市场上面还是没有ARM老谋深算，人家简单指令集一路走到底，授权卖指令集或者自己出公版，得到了苹果、三星、高通、MTK等许多大厂的青睐（苹果、高通、三星等厂商都是向ARM买指令集，再自己设计电路，大概是嫌ARM自己的芯片效能不够；然而联发科和其他几家厂商买的是IP（公版）来兜自己的芯片，不自己从头设计电路），细水长流，进过多年顺风打野，最后打出一身神装出来carry。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;反观intel，执着于自己x86架构，也用复杂指令集芯片打入过移动市场，奈何功耗扛不住啊，（充电两小时，装逼5分钟，只是个夸张比喻，勿当真）虽然后来又出了Atom的低功耗处理器，奈何市场已被ARM吞食大半，自己名气也没有打出，最后只能默默凉凉了。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;intel在PC市场上霸主这么多年，实力肯定不是盖的，所以我们这次选个intel在hwc模块的实现来看看（其实是因为TI、高通的实现有些复杂，比较晦涩，三星也倒是比较容易看懂，但是也没有intel代码这么人性化=。=）&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;HWC选取合成类型&quot;&gt;&lt;a href=&quot;#HWC选取合成类型&quot; class=&quot;headerlink&quot; title=&quot;HWC选取合成类型&quot;&gt;&lt;/a&gt;HWC选取合成类型&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面讲到mHwc-&amp;gt;prepare(mHwc, mNumDisplays, mLists);对所有显示屏中所有Layer作合成准备（此时也可以开始发送合成的命令码下去，启动硬件合成，但不需要等待完成），hwcomposer需要正确汇报每个Layer的composetype，以告知SurfaceFlinger是否需要额外处理。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;实现位于/hardware/intel/img/hwcomposer/common/base/Hwcomposer.cpp，我们找一个公共模块：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; Hwcomposer::prepare(&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; numDisplays,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                          &lt;span class=&quot;keyword&quot;&gt;hwc_display_contents_1_t&lt;/span&gt;** displays)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; ret = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    RETURN_FALSE_IF_NOT_INIT();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;display count = %d&quot;&lt;/span&gt;, numDisplays);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!numDisplays || !displays) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ELOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;invalid parameters&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//检查显示屏相关信息，处理热插拔消息&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDisplayAnalyzer-&amp;gt;analyzeContents(numDisplays, displays);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// disable reclaimed planes&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//disable掉所有回收的显示平面&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mPlaneManager-&amp;gt;disableReclaimedPlanes();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// reclaim all allocated planes if possible&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果可能，回首所有已经申请过的显示平面&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; numDisplays; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (i &amp;gt;= mDisplayDevices.size()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        IDisplayDevice *device = mDisplayDevices.itemAt(i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!device) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            VLOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;device %d doesn&#39;t exist&quot;&lt;/span&gt;, i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//检查显示屏几何区域是否有变化&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        device-&amp;gt;prePrepare(displays[i]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; numDisplays; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (i &amp;gt;= mDisplayDevices.size()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        IDisplayDevice *device = mDisplayDevices.itemAt(i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!device) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            VLOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;device %d doesn&#39;t exist&quot;&lt;/span&gt;, i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//最重要的一行：更新HwcLayer，选择合成类型&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ret = device-&amp;gt;prepare(displays[i]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ret == &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ELOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;failed to do prepare for device %d&quot;&lt;/span&gt;, i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; ret;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上述就是选取合成类型的步骤：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）检查显示屏相关信息，处理热插拔消息；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）disable掉所有回收的显示平面；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）检查显示屏几何区域是否有变化；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）最重要的一行：更新HwcLayer，选择合成类型。&lt;/p&gt;
&lt;h2 id=&quot;流程细节&quot;&gt;&lt;a href=&quot;#流程细节&quot; class=&quot;headerlink&quot; title=&quot;流程细节&quot;&gt;&lt;/a&gt;流程细节&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们分步查看：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）检查显示屏相关信息，处理热插拔消息。位于hardware/intel/img/hwcomposer/common/base/DisplayAnalyzer.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; DisplayAnalyzer::analyzeContents(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; numDisplays, &lt;span class=&quot;keyword&quot;&gt;hwc_display_contents_1_t&lt;/span&gt;** displays)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// cache and use them only in this context during analysis&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCachedNumDisplays = numDisplays;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCachedDisplays = displays;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//处理pending的事件&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    handlePendingEvents();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; DisplayAnalyzer::handlePendingEvents()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// handle one event per analysis to avoid blocking surface flinger&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// some event may take lengthy time to process&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Event e;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!getEvent(e)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt; (e.type) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HOTPLUG_EVENT:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//处理热插拔&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        handleHotplugEvent(e.bValue);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; DisplayAnalyzer::handleHotplugEvent(&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; connected)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (connected) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; mCachedNumDisplays; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//将合成类型设置成HWC_FRAMEBUFFER&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            setCompositionType(i, HWC_FRAMEBUFFER, &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这就是处理热插拔消息，然后将cache的显示屏合成类型设置成HWC_FRAMEBUFFER，表示用Open GL合成。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）disable掉所有回收的显示平面。位于hardware/intel/img/hwcomposer/common/planes/DisplayPlaneManager.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; DisplayPlaneManager::disableReclaimedPlanes()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; i, j;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; ret;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    RETURN_VOID_IF_NOT_INIT();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; DisplayPlane::PLANE_MAX; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// disable reclaimed planes&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mReclaimedPlanes[i]) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (j = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; j &amp;lt; mPlaneCount[i]; j++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; bit = (&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt; &amp;lt;&amp;lt; j);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mReclaimedPlanes[i] &amp;amp; bit) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    DisplayPlane* plane = mPlanes[i].itemAt(j);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// check plane state first&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    ret = plane-&amp;gt;isDisabled();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// reset plane&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ret)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        ret = plane-&amp;gt;reset();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ret) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// only merge into free bitmap if it is successfully disabled and reset&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// otherwise, plane will be disabled and reset again.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        mFreePlanes[i] |=bit;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        mReclaimedPlanes[i] &amp;amp;= ~bit;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;disable所有已经回收planes，检查plane是否已经disable，然后将其reset，如果成功了，就合并进入空闲的bitmap，如果没有就要重新disabled and reset。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）检查显示屏几何区域是否有变化，遍历每一个显示屏，调用device-&amp;gt;prePrepare(displays[i]);我们看一下物理屏幕，位于hardware/intel/img/hwcomposer/common/devices/PhysicalDevice.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; PhysicalDevice::prePrepare(&lt;span class=&quot;keyword&quot;&gt;hwc_display_contents_1_t&lt;/span&gt; *display)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    RETURN_FALSE_IF_NOT_INIT();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// for a null list, delete hwc list&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mConnected || !display || mBlank) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mLayerList) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            DEINIT_AND_DELETE_OBJ(mLayerList);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// check if geometry is changed, if changed delete list&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((display-&amp;gt;flags &amp;amp; HWC_GEOMETRY_CHANGED) &amp;amp;&amp;amp; mLayerList) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        DEINIT_AND_DELETE_OBJ(mLayerList);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果是一个空的hwc list，就将其删除；然后检查几何区域是否变化，如果变了，也要删除hwc list。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）最重要的一行：更新HwcLayer，选择合成类型。依然是遍历每一个显示屏，然后调用prepare函数，依然位于hardware/intel/img/hwcomposer/common/devices/PhysicalDevice.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; PhysicalDevice::prepare(&lt;span class=&quot;keyword&quot;&gt;hwc_display_contents_1_t&lt;/span&gt; *display)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    RETURN_FALSE_IF_NOT_INIT();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mConnected || !display || mBlank)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// check if geometry is changed&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (display-&amp;gt;flags &amp;amp; HWC_GEOMETRY_CHANGED) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//上一步处理了几何区域变化，上出了hwc list，这一步重新创建&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        onGeometryChanged(display);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mLayerList) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        WLOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;null HWC layer list&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// update list with new list&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//更新hwc list使用重新new的，选取合成类型&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mLayerList-&amp;gt;update(display);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; PhysicalDevice::onGeometryChanged(&lt;span class=&quot;keyword&quot;&gt;hwc_display_contents_1_t&lt;/span&gt; *&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ELOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;list is NULL&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;disp = %d, layer number = %d&quot;&lt;/span&gt;, mType, &lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;-&amp;gt;numHwLayers);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;NOTE:&lt;/span&gt; should NOT be here&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mLayerList) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        WLOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;mLayerList exists&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        DEINIT_AND_DELETE_OBJ(mLayerList);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// create a new layer list&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//上一步处理了几何区域变化，上出了hwc list，这一步重新创建&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mLayerList = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; HwcLayerList(&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;, mType);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mLayerList) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        WLOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;failed to create layer list&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上一步处理了几何区域变化，上出了hwc list，这一步重新创建，在onGeometryChanged函数中得以体现。&lt;/p&gt;
&lt;h2 id=&quot;更新HwcLayerList&quot;&gt;&lt;a href=&quot;#更新HwcLayerList&quot; class=&quot;headerlink&quot; title=&quot;更新HwcLayerList&quot;&gt;&lt;/a&gt;更新HwcLayerList&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;那么选取合成类型就位于mLayerList-&amp;gt;update(display);，位于hardware/intel/img/hwcomposer/common/base/HwcLayerList.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; HwcLayerList::update(&lt;span class=&quot;keyword&quot;&gt;hwc_display_contents_1_t&lt;/span&gt; *&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; ret;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// basic check to make sure the consistance&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ELOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;null layer list&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;)&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;-&amp;gt;numHwLayers != mLayerCount) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ELOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;layer count doesn&#39;t match (%d, %d)&quot;&lt;/span&gt;, &lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;-&amp;gt;numHwLayers, mLayerCount);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// update list&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mList = &lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; ok = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// update all layers, call each layer&#39;s update()&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; mLayerCount; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        HwcLayer *hwcLayer = mLayers.itemAt(i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!hwcLayer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ELOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;no HWC layer for layer %d&quot;&lt;/span&gt;, i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//更新layer，如果更新返回false，则需要fallback回GLES去合成&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!hwcLayer-&amp;gt;update(&amp;amp;&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;-&amp;gt;hwLayers[i])) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ok = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hwcLayer-&amp;gt;setCompositionType(HWC_FORCE_FRAMEBUFFER);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!ok) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果上一步update有返回false的，就要把它fallback回GLES合成&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ILOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;overlay fallback to GLES. flags: %#x&quot;&lt;/span&gt;, &lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;-&amp;gt;flags);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; mLayerCount - &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            HwcLayer *hwcLayer = mLayers.itemAt(i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hwcLayer-&amp;gt;getPlane() &amp;amp;&amp;amp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                (hwcLayer-&amp;gt;getCompositionType() == HWC_OVERLAY ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                hwcLayer-&amp;gt;getCompositionType() == HWC_CURSOR_OVERLAY)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                hwcLayer-&amp;gt;setCompositionType(HWC_FRAMEBUFFER);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//最后一个layer是HWC_FRAMEBUFFER_TARGET合成目标，上面讲过&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mLayers.itemAt(mLayerCount - &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)-&amp;gt;setCompositionType(HWC_FRAMEBUFFER_TARGET);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//反初始化&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        deinitialize();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mList = &lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//初始化LayerList每一项&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        initialize();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// update all layers again after plane re-allocation&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//再次更新所有的layer，在plane重新申请之后&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; mLayerCount; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            HwcLayer *hwcLayer = mLayers.itemAt(i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!hwcLayer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ELOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;no HWC layer for layer %d&quot;&lt;/span&gt;, i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!hwcLayer-&amp;gt;update(&amp;amp;&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;-&amp;gt;hwLayers[i])) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                DLOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;fallback to GLES update failed on layer[%d]!\n&quot;&lt;/span&gt;, i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//建立只能合成选项，即选择OverLay还是FB&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    setupSmartComposition();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id=&quot;更新HwcLayer&quot;&gt;&lt;a href=&quot;#更新HwcLayer&quot; class=&quot;headerlink&quot; title=&quot;更新HwcLayer&quot;&gt;&lt;/a&gt;更新HwcLayer&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里依然要分步查看：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Part.1：我们可以看到，选取合成类型为Overlay还是FB就在hwcLayer-&amp;gt;update函数，如果返回false，就要fallback回GLES，剩余的都是OverLay。我们看看这个实现，位于hardware/intel/img/hwcomposer/common/base/HwcLayer.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; HwcLayer::update(&lt;span class=&quot;keyword&quot;&gt;hwc_layer_1_t&lt;/span&gt; *layer)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// update layer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mLayer = layer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//创建基本属性，从DataBuffer获取，也可是说是GraphicBuffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    setupAttributes();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// if not a FB layer &amp;amp; a plane was attached update plane&#39;s data buffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果不是一个FB layer并且plane已经被连接到更新data buffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mPlane) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//设置position位置信息&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mPlane-&amp;gt;setPosition(layer-&amp;gt;displayFrame.left,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            layer-&amp;gt;displayFrame.top,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            layer-&amp;gt;displayFrame.right - layer-&amp;gt;displayFrame.left,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            layer-&amp;gt;displayFrame.bottom - layer-&amp;gt;displayFrame.top);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//设置sourceCrop区域                    &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mPlane-&amp;gt;setSourceCrop(layer-&amp;gt;sourceCropf.left,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                              layer-&amp;gt;sourceCropf.top,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                              layer-&amp;gt;sourceCropf.right - layer-&amp;gt;sourceCropf.left,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                              layer-&amp;gt;sourceCropf.bottom - layer-&amp;gt;sourceCropf.top);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//设置矩阵变换                      &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mPlane-&amp;gt;setTransform(layer-&amp;gt;transform);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//透明度&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mPlane-&amp;gt;setPlaneAlpha(layer-&amp;gt;planeAlpha, layer-&amp;gt;blending);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//将layer的句柄设置给plane&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; ret = mPlane-&amp;gt;setDataBuffer((&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;)layer-&amp;gt;handle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ret == &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        DLOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;failed to set data buffer, reset handle to 0!!&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mHandle = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mIsProtected) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//如果不是被保护的buffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//典型的例子：旋转的buffer没有准备好或者句柄为null，就不能用OverLay&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// typical case: rotated buffer is not ready or handle is null&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//被保护的视频需要使用overlay去渲染，return true&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// protected video has to be rendered using overlay.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// if buffer is not ready overlay will still be attached to this layer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// but rendering needs to be skipped.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            WLOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;ignoring result of data buffer setting for protected video&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;先创建基本属性，从DataBuffer获取，也可是说是GraphicBuffer，我们看看setupAttributes函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; HwcLayer::setupAttributes()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;   &lt;span class=&quot;comment&quot;&gt;//如果如下属性发生改变，将mUpdated 置为true&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((mLayer-&amp;gt;flags &amp;amp; HWC_SKIP_LAYER) ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mTransform != mLayer-&amp;gt;transform ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSourceCropf != mLayer-&amp;gt;sourceCropf ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mDisplayFrame != mLayer-&amp;gt;displayFrame ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mHandle != (&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;)mLayer-&amp;gt;handle ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        DisplayQuery::isVideoFormat(mFormat)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;TODO:&lt;/span&gt; same handle does not mean there is always no update&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mUpdated = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// update handle always as it can become &quot;NULL&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// if the given layer is not ready&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果指定的layer没有准备好，那么handle句柄就会变成null，所以要更新句柄的值&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mTransform = mLayer-&amp;gt;transform;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSourceCropf = mLayer-&amp;gt;sourceCropf;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDisplayFrame = mLayer-&amp;gt;displayFrame;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mHandle = (&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;)mLayer-&amp;gt;handle;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//其实属性已经被设置，return&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mFormat != DataBuffer::FORMAT_INVALID) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// other attributes have been set.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//句柄为null，return&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mLayer-&amp;gt;handle == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        VLOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;invalid handle&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//获取BufferManager&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BufferManager *bm = Hwcomposer::getInstance().getBufferManager();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (bm == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;TODO:&lt;/span&gt; this check is redundant&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//锁定图形缓冲区&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    DataBuffer *buffer = bm-&amp;gt;lockDataBuffer((&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;)mLayer-&amp;gt;handle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!buffer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;         ELOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;failed to get buffer&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;span class=&quot;comment&quot;&gt;//获取图形缓冲区属性，并设置给全局变量&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mFormat = buffer-&amp;gt;getFormat();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mWidth = buffer-&amp;gt;getWidth();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mHeight = buffer-&amp;gt;getHeight();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mStride = buffer-&amp;gt;getStride();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mPriority = (mSourceCropf.right - mSourceCropf.left) * (mSourceCropf.bottom - mSourceCropf.top);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mPriority &amp;lt;&amp;lt;= LAYER_PRIORITY_SIZE_OFFSET;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mPriority |= mIndex;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        GraphicBuffer *gBuffer = (GraphicBuffer*)buffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mUsage = gBuffer-&amp;gt;getUsage();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mIsProtected = GraphicBuffer::isProtectedBuffer((GraphicBuffer*)buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mIsProtected) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mPriority |= LAYER_PRIORITY_PROTECTED;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (PlaneCapabilities::isFormatSupported(DisplayPlane::PLANE_OVERLAY, &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mPriority |= LAYER_PRIORITY_OVERLAY;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//获取完之后释放&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        bm-&amp;gt;unlockDataBuffer(buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这段代码要是参考之前Gralloc模块应该有点印象，就是锁定图形缓冲区，获取图形缓冲区属性，并设置给全局变量，获取完之后释放。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;回到HwcLayer::update，之后判断如果不是一个FB layer并且plane已经被连接到更新data buffer，就要设置position位置信息、设置sourceCrop区域、设置矩阵变换 、透明度。&lt;/p&gt;
&lt;h2 id=&quot;映射过程&quot;&gt;&lt;a href=&quot;#映射过程&quot; class=&quot;headerlink&quot; title=&quot;映射过程&quot;&gt;&lt;/a&gt;映射过程&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后将layer的句柄设置给plane，我们看看这个实现，位于hardware/intel/img/hwcomposer/common/planes/DisplayPlane.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; DisplayPlane::setDataBuffer(&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; handle)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    DataBuffer *buffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BufferMapper *mapper;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;ssize_t&lt;/span&gt; index;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; ret;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; isCompression;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//获取buffermanager&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BufferManager *bm = Hwcomposer::getInstance().getBufferManager();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    RETURN_FALSE_IF_NOT_INIT();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;handle = %#x&quot;&lt;/span&gt;, handle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!handle) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        WLOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;invalid buffer handle&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// do not need to update the buffer handle&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果不是当前保存句柄，加上CHANGE标签&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mCurrentDataBuffer != handle)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mUpdateMasks |= PLANE_BUFFER_CHANGED;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// if no update then do Not need set data buffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mUpdateMasks)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//锁定缓冲区&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    buffer = bm-&amp;gt;lockDataBuffer(handle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!buffer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ELOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;failed to get buffer&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mIsProtectedBuffer = GraphicBuffer::isProtectedBuffer((GraphicBuffer*)buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    isCompression = GraphicBuffer::isCompressionBuffer((GraphicBuffer*)buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// map buffer if it&#39;s not in cache&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果映射区域不在缓存cache中，就要重新映射&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    index = mDataBuffers.indexOfKey(buffer-&amp;gt;getKey());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (index &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        VLOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;unmapped buffer, mapping...&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//映射buffer，并加入缓存&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mapper = mapBuffer(buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mapper) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ELOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;failed to map buffer %#x&quot;&lt;/span&gt;, handle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            bm-&amp;gt;unlockDataBuffer(buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        VLOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;got mapper in saved data buffers and update source Crop&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mapper = mDataBuffers.valueAt(index);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// always update source crop to mapper&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//更新crop区域&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mapper-&amp;gt;setCrop(mSrcCrop.x, mSrcCrop.y, mSrcCrop.w, mSrcCrop.h);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mapper-&amp;gt;setIsCompression(isCompression);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// unlock buffer after getting mapper&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//映射区域之后释放缓冲区&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    bm-&amp;gt;unlockDataBuffer(buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    buffer = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//将映射区域设置给plane&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ret = setDataBuffer(*mapper);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ret) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//如果成功了，就将handle赋给mCurrentDataBuffer ，并且更新活跃的buffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mCurrentDataBuffer = handle;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// update active buffers&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        updateActiveBuffers(mapper);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; ret;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;核心就是获取显示屏的BufferManager，然后锁定图形缓冲区，然后映射buffer，并加入缓存，映射区域之后释放缓冲区，将映射区域设置给plane。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;映射实现如下：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;BufferMapper* DisplayPlane::mapBuffer(DataBuffer *buffer)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BufferManager *bm = Hwcomposer::getInstance().getBufferManager();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// invalidate buffer cache  if cache is full&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//cache满了就要清除&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;)mDataBuffers.size() &amp;gt;= mCacheCapacity) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        invalidateBufferCache();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//映射plane内存区域&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BufferMapper *mapper = bm-&amp;gt;&lt;span class=&quot;built_in&quot;&gt;map&lt;/span&gt;(*buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mapper) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ELOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;failed to map buffer&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// add it to data buffers&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//映射成功后就将这个句柄加入缓存&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;ssize_t&lt;/span&gt; index = mDataBuffers.add(buffer-&amp;gt;getKey(), mapper);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (index &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ELOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;failed to add mapper&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        bm-&amp;gt;unmap(mapper);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mapper;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; DisplayPlane::invalidateBufferCache()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BufferManager *bm = Hwcomposer::getInstance().getBufferManager();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BufferMapper* mapper;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    RETURN_VOID_IF_NOT_INIT();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; mDataBuffers.size(); i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mapper = mDataBuffers.valueAt(i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        bm-&amp;gt;unmap(mapper);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDataBuffers.clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// reset current buffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentDataBuffer = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;之后将映射区域设置给plane，如果成功了，就将handle赋给mCurrentDataBuffer ，并且更新活跃的buffer：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; DisplayPlane::updateActiveBuffers(BufferMapper *mapper)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BufferManager *bm = Hwcomposer::getInstance().getBufferManager();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// unmap the first entry (oldest buffer)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mActiveBuffers.size() &amp;gt;= MIN_DATA_BUFFER_COUNT) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        BufferMapper *oldest = mActiveBuffers.itemAt(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        bm-&amp;gt;unmap(oldest);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mActiveBuffers.removeAt(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// queue it to active buffers&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!isActiveBuffer(mapper)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mapper-&amp;gt;incRef();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mActiveBuffers.push_back(mapper);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;也就是移除最老的映射buffer，然后新增加一个最新的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果设置给plane不成功，即没有可用的内存区域或者不匹配，则不能使用OverLay合成，返回false，就要是OpenGL了。&lt;/p&gt;
&lt;h2 id=&quot;初始化和反初始化&quot;&gt;&lt;a href=&quot;#初始化和反初始化&quot; class=&quot;headerlink&quot; title=&quot;初始化和反初始化&quot;&gt;&lt;/a&gt;初始化和反初始化&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;回到上面HwcLayerList::update，继续往下走。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后就是先反初始化deinitialize：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; HwcLayerList::deinitialize()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mLayerCount == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    DisplayPlaneManager *planeManager = Hwcomposer::getInstance().getPlaneManager();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; mLayerCount; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        HwcLayer *hwcLayer = mLayers.itemAt(i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hwcLayer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            DisplayPlane *plane = hwcLayer-&amp;gt;detachPlane();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (plane) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                planeManager-&amp;gt;reclaimPlane(mDisplayIndex, *plane);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;delete&lt;/span&gt; hwcLayer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mLayers.clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFBLayers.clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mOverlayCandidates.clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSpriteCandidates.clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCursorCandidates.clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mZOrderConfig.clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFrameBufferTarget = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mLayerCount = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;反初始化就是清除一些变量。然后是初始化initialize：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;96&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;97&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;98&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;99&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;100&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;101&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;102&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;103&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;104&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; HwcLayerList::initialize()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mList || mList-&amp;gt;numHwLayers == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ELOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;invalid hwc list&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//设置一些变量&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mLayerCount = (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;)mList-&amp;gt;numHwLayers;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mLayers.setCapacity(mLayerCount);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFBLayers.setCapacity(mLayerCount);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSpriteCandidates.setCapacity(mLayerCount);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mOverlayCandidates.setCapacity(mLayerCount);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCursorCandidates.setCapacity(mLayerCount);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mZOrderConfig.setCapacity(mLayerCount);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Hwcomposer&amp;amp; hwc = Hwcomposer::getInstance();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    PriorityVector rgbOverlayLayers;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    rgbOverlayLayers.setCapacity(mLayerCount);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//根据不同合成类型设置hwcLayer的type&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; mLayerCount; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;hwc_layer_1_t&lt;/span&gt; *layer = &amp;amp;mList-&amp;gt;hwLayers[i];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!layer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            DEINIT_AND_RETURN_FALSE(&lt;span class=&quot;string&quot;&gt;&quot;layer %d is null&quot;&lt;/span&gt;, i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        HwcLayer *hwcLayer = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; HwcLayer(i, layer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!hwcLayer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            DEINIT_AND_RETURN_FALSE(&lt;span class=&quot;string&quot;&gt;&quot;failed to allocate hwc layer %d&quot;&lt;/span&gt;, i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (layer-&amp;gt;compositionType == HWC_FRAMEBUFFER_TARGET) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//HWC_FRAMEBUFFER_TARGET&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hwcLayer-&amp;gt;setType(HwcLayer::LAYER_FRAMEBUFFER_TARGET);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mFrameBufferTarget = hwcLayer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (layer-&amp;gt;compositionType == HWC_OVERLAY)&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// skipped layer, filtered by Display Analyzer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hwcLayer-&amp;gt;setType(HwcLayer::LAYER_SKIPPED);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (layer-&amp;gt;compositionType == HWC_FORCE_FRAMEBUFFER) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//HWC_FORCE_FRAMEBUFFER&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            layer-&amp;gt;compositionType = HWC_FRAMEBUFFER;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hwcLayer-&amp;gt;setType(HwcLayer::LAYER_FORCE_FB);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// add layer to FB layer list for zorder check during plane assignment&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mFBLayers.add(hwcLayer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;  &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (layer-&amp;gt;compositionType == HWC_FRAMEBUFFER) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//HWC_FRAMEBUFFER&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// by default use GPU composition&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//默认由GPU合成&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hwcLayer-&amp;gt;setType(HwcLayer::LAYER_FB);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mFBLayers.add(hwcLayer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//检查是否支持cursor overlay&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (checkCursorSupported(hwcLayer)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mCursorCandidates.add(hwcLayer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (checkRgbOverlaySupported(hwcLayer)) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//检查是否支持rgb overlay&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                rgbOverlayLayers.add(hwcLayer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (checkSupported(DisplayPlane::PLANE_SPRITE, hwcLayer)) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//检查是否支持PLANE_SPRITE&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mSpriteCandidates.add(hwcLayer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (checkSupported(DisplayPlane::PLANE_OVERLAY, hwcLayer)) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//是否支持PLANE_OVERLAY&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mOverlayCandidates.add(hwcLayer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// noncandidate layer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (layer-&amp;gt;compositionType == HWC_SIDEBAND)&amp;#123;&lt;span class=&quot;comment&quot;&gt;//HWC_SIDEBAND&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hwcLayer-&amp;gt;setType(HwcLayer::LAYER_SIDEBAND);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            DEINIT_AND_RETURN_FALSE(&lt;span class=&quot;string&quot;&gt;&quot;invalid composition type %d&quot;&lt;/span&gt;, layer-&amp;gt;compositionType);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// add layer to layer list&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mLayers.add(hwcLayer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mFrameBufferTarget == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ELOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;no frame buffer target?&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// If has layer besides of FB_Target, but no FBLayers, skip plane allocation&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Note: There is case that SF passes down a layerlist with only FB_Target&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// layer; we need to have this FB_Target to be flipped as well, otherwise it&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// will have the buffer queue blocked. (The buffer hold by driver cannot be&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// released if new buffers&#39; flip is skipped).&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((mFBLayers.size() == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;amp;&amp;amp; (mLayers.size() &amp;gt; &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        VLOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;no FB layers, skip plane allocation&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; hasOverlay = mOverlayCandidates.size() != &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (rgbOverlayLayers.size()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        HwcLayer *hwcLayer = rgbOverlayLayers.top();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hasOverlay) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSpriteCandidates.add(hwcLayer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mOverlayCandidates.add(hwcLayer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        rgbOverlayLayers.removeItemsAt(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!DisplayQuery::forceFbScaling(mDisplayIndex)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        allocatePlanes();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// force GLES composition on all layers, then use GPU or hardware&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// overlay to scale buffer to match display resolution&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        assignPrimaryPlane();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//dump();&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这一段核心就是根据不同合成类型设置hwcLayer的type，合成类型有HWC_FRAMEBUFFER_TARGET、HWC_FORCE_FRAMEBUFFER、HWC_FRAMEBUFFER、HWC_SIDEBAND，又在HWC_FRAMEBUFFER检测：检查是否支持cursor overlay、检查是否支持rgb overlay、检查是否支持PLANE_SPRITE、是否支持PLANE_OVERLAY，如果支持就要加入OverLay合成。&lt;/p&gt;
&lt;h2 id=&quot;开始智能合成&quot;&gt;&lt;a href=&quot;#开始智能合成&quot; class=&quot;headerlink&quot; title=&quot;开始智能合成&quot;&gt;&lt;/a&gt;开始智能合成&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;继续回到上面，进行最后一步setupSmartComposition，建立只能合成选项，即选择OverLay还是FB：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; HwcLayerList::setupSmartComposition()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//默认都是HWC_OVERLAY&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; compositionType = HWC_OVERLAY;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    HwcLayer *hwcLayer = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// setup smart composition only there&#39;s no update on all FB layers&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果所有的FB layer没有更新了就开始建立智能合成&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; mFBLayers.size(); i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        hwcLayer = mFBLayers.itemAt(i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hwcLayer-&amp;gt;isUpdated()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            compositionType = HWC_FRAMEBUFFER;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    VLOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;smart composition enabled %s&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           (compositionType == HWC_OVERLAY) ? &lt;span class=&quot;string&quot;&gt;&quot;TRUE&quot;&lt;/span&gt; : &lt;span class=&quot;string&quot;&gt;&quot;FALSE&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//开始只能合成，当compositionType == HWC_OVERLAY就是硬件合成，否则其他都是FB模式       &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; mFBLayers.size(); i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        hwcLayer = mFBLayers.itemAt(i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt; (hwcLayer-&amp;gt;getType()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HwcLayer::LAYER_FB:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HwcLayer::LAYER_FORCE_FB:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hwcLayer-&amp;gt;setCompositionType(compositionType);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;default&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ELOGTRACE(&lt;span class=&quot;string&quot;&gt;&quot;Invalid layer type %d&quot;&lt;/span&gt;, hwcLayer-&amp;gt;getType());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面就是开始智能合成，当compositionType == HWC_OVERLAY就是硬件合成，否则其他都是FB模式。&lt;/p&gt;
&lt;h1 id=&quot;小结&quot;&gt;&lt;a href=&quot;#小结&quot; class=&quot;headerlink&quot; title=&quot;小结&quot;&gt;&lt;/a&gt;小结&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上述就是hwc硬件选取合成类型的模块，流程分析比较粗略，估计有好多不正确的地方，欢迎大家指正，我好在第一时间修改。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%E4%B8%80%29%28PostView%29--%E9%99%84%EF%BC%9A%E7%A1%AC%E4%BB%B6HWC%E9%80%89%E5%8F%96%E5%90%88%E6%88%90%E7%B1%BB%E5%9E%8B%EF%BC%88Intel%EF%BC%89/7c4f157bly1fkqyqfbz8jj20go0p07mv.jpg&quot; alt=&quot;meizi&quot;&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里说点题外话，高通最近势头正猛啊，回拒了博通的恶意收购，又出了骁龙835进军PC市场，拉着AMD一起干英特尔。英特尔在移动设备市场上面还是没有ARM老谋深算，人家简单指令集一路走到底，授权卖指令集或者自己出公版，得到了苹果、三星、高通、MTK等许多大厂的青睐（苹果、高通、三星等厂商都是向ARM买指令集，再自己设计电路，大概是嫌ARM自己的芯片效能不够；然而联发科和其他几家厂商买的是IP（公版）来兜自己的芯片，不自己从头设计电路），细水长流，进过多年顺风打野，最后打出一身神装出来carry。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;反观intel，执着于自己x86架构，也用复杂指令集芯片打入过移动市场，奈何功耗扛不住啊，（充电两小时，装逼5分钟，只是个夸张比喻，勿当真）虽然后来又出了Atom的低功耗处理器，奈何市场已被ARM吞食大半，自己名气也没有打出，最后只能默默凉凉了。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;intel在PC市场上霸主这么多年，实力肯定不是盖的，所以我们这次选个intel在hwc模块的实现来看看（其实是因为TI、高通的实现有些复杂，比较晦涩，三星也倒是比较容易看懂，但是也没有intel代码这么人性化=。=）&lt;br&gt;
    
    </summary>
    
      <category term="Android技术点" scheme="http://windrunnerlihuan.com/categories/Android%E6%8A%80%E6%9C%AF%E7%82%B9/"/>
    
    
      <category term="SurfaceFlinger" scheme="http://windrunnerlihuan.com/tags/SurfaceFlinger/"/>
    
  </entry>
  
  <entry>
    <title>Android SurfaceFlinger 学习之路(十一)----合成Layer之准备合成</title>
    <link href="http://windrunnerlihuan.com/2017/12/01/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%8D%81%E4%B8%80-%E5%90%88%E6%88%90Layer%E4%B9%8B%E5%87%86%E5%A4%87%E5%90%88%E6%88%90/"/>
    <id>http://windrunnerlihuan.com/2017/12/01/Android-SurfaceFlinger-学习之路-十一-合成Layer之准备合成/</id>
    <published>2017-12-01T06:31:11.000Z</published>
    <updated>2019-01-06T07:29:26.105Z</updated>
    
    <content type="html">&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上一篇我们主要分析了计算Layer的脏区域流程，其中涉及了Buffer状态迁移的后两个步骤：ACQUIRED、RELEADED。本届开始就是正式的合成步骤——REFRESH。但是这个步骤比较复杂，所以先分析合成前的准备工作：重建Layer栈与初始化硬件合成器。&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;合成准备&quot;&gt;&lt;a href=&quot;#合成准备&quot; class=&quot;headerlink&quot; title=&quot;合成准备&quot;&gt;&lt;/a&gt;合成准备&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当Vsync到来时候，SF会处理MessageQueue的INVALIDATE消息，消息最后一部再次触发REFRESH消息，进入合成阶段。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个流程在SF的handleMessageRefresh函数，位于frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::handleMessageRefresh() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*调Layer的onPreComposition方法，主要是标志一下Layer已经被用于合成*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    preComposition();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*若Layer的位置/先后顺序/可见性发生变化，重新计算Layer的目标合成区域和先后顺序*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    rebuildLayerStacks();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*配置硬件合成器，调hwc的prepare方法*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    setUpHWComposer();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*当打开开发者选项中的“显示Surface刷新”时，额外为产生变化的图层绘制闪烁动画*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    doDebugFlashRegions();&lt;span class=&quot;comment&quot;&gt;//ignore&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*执行合成主体，对3D合成而言，调opengl的drawcall，对硬件合成而言，调hwc的set方法*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    doComposition();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*主要用于调试，调Layer的onPostComposition方法*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    postComposition();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个函数每一步的功能都很清晰，看起来简单粗暴。综合上面几节，流程图如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%E4%B8%80%29----%E5%90%88%E6%88%90Layer%E4%B9%8B%E5%87%86%E5%A4%87%E5%90%88%E6%88%90/composition.png&quot; alt=&quot;合成流程&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;每一部的功能，我们会在接下来每一步详细分析。&lt;/p&gt;
&lt;h1 id=&quot;流程分析&quot;&gt;&lt;a href=&quot;#流程分析&quot; class=&quot;headerlink&quot; title=&quot;流程分析&quot;&gt;&lt;/a&gt;流程分析&lt;/h1&gt;&lt;h2 id=&quot;preComposition&quot;&gt;&lt;a href=&quot;#preComposition&quot; class=&quot;headerlink&quot; title=&quot;preComposition&quot;&gt;&lt;/a&gt;preComposition&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;调Layer的onPreComposition方法，主要是标志一下Layer已经被用于合成。我们看看preComposition函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::preComposition()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; needExtraInvalidate = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; LayerVector&amp;amp; &lt;span class=&quot;title&quot;&gt;layers&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mDrawingState.layersSortedByZ)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; count = layers.size();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; i&amp;lt;count ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (layers[i]-&amp;gt;onPreComposition()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            needExtraInvalidate = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (needExtraInvalidate) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        signalLayerUpdate();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;代码很简单，一共就三步：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）获取全部经过z-order排序的layer；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）每个layer调用onPrecomposition判断是否需要触发vsync更新；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）Layer update。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们看看第二步的判断逻辑，Layer的onPrecomposition函数，位于frameworks/native/services/surfaceflinger/Layer.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; Layer::onPreComposition() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mRefreshPending = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;span class=&quot;comment&quot;&gt;//标志一下Layer已经被用于合成&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//当layer里存放被queue的frame以后，就会出发layer update&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mQueuedFrames &amp;gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; || mSidebandStreamChanged;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们在&lt;a href=&quot;http://windrunnerlihuan.com/2017/07/03/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%85%AB-Surface%E7%AE%A1%E7%90%86%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BA/&quot;&gt;Android SurfaceFlinger 学习之路(八)—-Surface管理图形缓冲区&lt;/a&gt;中讲过，当Buffer被queue回BufferQueue，状态迁移到QUEUED，就会回调Layer的onFrameAvailable函数，将mQueuedFrames自动+1。所以当vsync到来时候，就会根据这个判断时候更新layer。&lt;/p&gt;
&lt;h2 id=&quot;rebuildLayerStacks&quot;&gt;&lt;a href=&quot;#rebuildLayerStacks&quot; class=&quot;headerlink&quot; title=&quot;rebuildLayerStacks&quot;&gt;&lt;/a&gt;rebuildLayerStacks&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;若Layer的位置/先后顺序/可见性发生变化，重新计算Layer的目标合成区域和先后顺序。我们要看看rebuildLayerStacks函数：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;void SurfaceFlinger::rebuildLayerStacks() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // rebuild the visible layer list per screen&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //系统显示屏以及各个应用程序窗口的属性变化时&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (CC_UNLIKELY(mVisibleRegionsDirty)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mVisibleRegionsDirty = false;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //将mHwWorkListDirty 标记为true&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        invalidateHwcGeometry();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //获取当前应用程序所有按照z-order排列的layer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const LayerVector&amp;amp; layers(mDrawingState.layersSortedByZ);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //遍历每一个显示屏&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        for (size_t dpy=0 ; dpy&amp;lt;mDisplays.size() ; dpy++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Region opaqueRegion;//全局不透明区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Region dirtyRegion;//需要重新render的脏区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Vector&amp;lt; sp&amp;lt;Layer&amp;gt; &amp;gt; layersSortedByZ;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const sp&amp;lt;DisplayDevice&amp;gt;&amp;amp; hw(mDisplays[dpy]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const Transform&amp;amp; tr(hw-&amp;gt;getTransform());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const Rect bounds(hw-&amp;gt;getBounds());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (hw-&amp;gt;isDisplayOn()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //计算当前显示屏各个应用程序的可见区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                SurfaceFlinger::computeVisibleRegions(layers,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        hw-&amp;gt;getLayerStack(), dirtyRegion, opaqueRegion);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                const size_t count = layers.size();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                for (size_t i=0 ; i&amp;lt;count ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    const sp&amp;lt;Layer&amp;gt;&amp;amp; layer(layers[i]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    const Layer::State&amp;amp; s(layer-&amp;gt;getDrawingState());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    if (s.layerStack == hw-&amp;gt;getLayerStack()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        //可见不透明的区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        Region drawRegion(tr.transform(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                layer-&amp;gt;visibleNonTransparentRegion));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        drawRegion.andSelf(bounds);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        if (!drawRegion.isEmpty()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            //添加进入z-order排列的layer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            layersSortedByZ.add(layer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //z-order排列的layer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hw-&amp;gt;setVisibleLayersSortedByZ(layersSortedByZ);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //显示屏大小&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hw-&amp;gt;undefinedRegion.set(bounds);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //减去不透明区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hw-&amp;gt;undefinedRegion.subtractSelf(tr.transform(opaqueRegion));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //累加脏区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hw-&amp;gt;dirtyRegion.orSelf(dirtyRegion);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;void SurfaceFlinger::invalidateHwcGeometry()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mHwWorkListDirty = true;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;流程如下：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）从上一节的内容可以知道，当SurfaceFlinger服务在处理系统显示屏以及各个应用程序窗口的属性变化时，如果发现需要重新计算各个应用程序窗口的可见区域，那么就会将SurfaceFlinger类的成员变量mVisibleRegionsDirty的值设置为true。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;进入判断逻辑之后，将成员变量mVisibleRegionsDirty的值设置为false了，因为这时候系统中各个应用程序窗口的可见区域开始计算了。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）函数接下来通过SurfaceFlinger类的成员变量mDrawingState所描述的一个State对象的成员变量layersSortedByZ来获得系统当前所有的应用程序窗口，并且保存在一个类型为LayerVector的向量layers中。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）SurfaceFlinger类的成员函数computeVisibleRegions在计算完成各个应用程序窗口的可见区域之后，会得到一个全局不透明区域，保存在输出参数opaqueRegion中。这个全局不透明区域就是接下来需要渲染的，一般情况下，它的大小就应该等于显示屏的大小，即变量hw-&amp;gt;getBounds()所描述的区域。&lt;strong&gt;在异常情况下，可能会导致显示屏区域bounds大于全局不透明区域opaqueRegion，这时候前者减去后者就可以得到一些称为“虫洞”的区域。由于这些虫洞区域不会被各个应用程序窗口覆盖，因此，SurfaceFlinger服务需要对它们进行特殊处理，即以一种特殊的方式来渲染它们。在后面的部分内容中，我们就会看到SurfaceFlinger服务是通过调用SurfaceFlinger类的成员函数drawWormhole来渲染这些虫洞的。&lt;/strong&gt;&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）dirtyRegion是需要被刷新的。 opaqueRegion 不透明区域，layer是按Z-order排序的，左右排在前面的opaqueRegion 会挡住后面的layer。Region drawRegion(tr.transform( layer-&amp;gt;visibleNonTransparentRegion));程序需要进一步得出每个layer 绘制的区域。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;5）将结果保存到hw中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以上述流程的重点就是computeVisibleRegions就算过程，我们详细分析这个流程。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;再计算可见区域之前，我们要了解一些概念。&lt;/p&gt;
&lt;h3 id=&quot;相关区域概述&quot;&gt;&lt;a href=&quot;#相关区域概述&quot; class=&quot;headerlink&quot; title=&quot;相关区域概述&quot;&gt;&lt;/a&gt;相关区域概述&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在分析源码前，我们自己先来想一下，图层中什么样的区域是可见的呢？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Z-order&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;layer的z-order无疑是第一考虑的要素。因为排在越前面的图层，其获得曝光的机率越大，可见的区域也可能越大，如下图所示：&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%E4%B8%80%29----%E5%90%88%E6%88%90Layer%E4%B9%8B%E5%87%86%E5%A4%87%E5%90%88%E6%88%90/zorder.jpg&quot; alt=&quot;z-order&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以在计算可见性时，是按照Z-order由上而下进行的。假如一个layer的某个区域被确定为可见，那么与之相对应的它下面的所有图层区域都会被遮盖而不可见。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;透明度&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;虽然越前面的layer优先级越高，但这并不代表后面的图层完全没有机会。只要前一个layer不是完全不透明的，那么从理论上来讲用户就应该能“透过”这部分区域看到后面的内容。&lt;/li&gt;
&lt;li&gt;图层大小&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;与透明度一样，图层大小也直接影响到其可见区域。因为每个layer都是有大有小的，即便前一个layer是完全不透明的，但只要它的尺寸没有达到“满屏”，那么比它z-order小的图层还是有机会暴露出来的。这也是我们需要考虑的因素之一。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;因此我们要我们首先解释一些与应用程序窗口相关的概念：&lt;strong&gt;可见区域（Visible Region）、透明区域（Transparent Region）、半透明区域（Translucent Region）、完全不透明区域（Opaque Region）和被覆盖区域（Covered Region）。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;假设一个应用程序窗口的宽度和高度分别为w和h，如图所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%E4%B8%80%29----%E5%90%88%E6%88%90Layer%E4%B9%8B%E5%87%86%E5%A4%87%E5%90%88%E6%88%90/wh.jpg&quot; alt=&quot;wh&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;那么我们就可以将由(0,0)、(0, w)、(0, h)和(w,h)四个点组成的区域称为应用程序窗口的&lt;strong&gt;可见区域&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; 接下来，我们可以在一个应用程序窗口的可见区域挖一个洞出来，如下图所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%E4%B8%80%29----%E5%90%88%E6%88%90Layer%E4%B9%8B%E5%87%86%E5%A4%87%E5%90%88%E6%88%90/whblank.jpg&quot; alt=&quot;whblank&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这时候应用程序窗口真正的可见区域就需要减去中间被挖出来的洞。这个被挖出来的洞就称为应用程序窗口的&lt;strong&gt;透明可见区域&lt;/strong&gt;。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果应用程序窗口的可见区域的Alpha通道大于0并且小255，那么我们就认为应用程序窗口的可见区域是&lt;strong&gt;半透明的&lt;/strong&gt;。有两种极端情况，即当应用程序窗口的可见区域的Alpha通道等于0或者255的时候。当等于0的时候，我们就认为应用程序窗口的可见区域是&lt;strong&gt;透明的&lt;/strong&gt;，就如图5所示的洞一样，而当等于255的时候，我们就认为应用程序窗口的可见区域是&lt;strong&gt;完全不透明的&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面我们讨论的应用程序窗口的可见区域是基于单个应用程序窗口而言的，当多个应用程序窗口叠加在一起的时候，在讨论一个应用程序窗口的可见区域的时候，就需要考虑位于它上面的其它应用程序窗口的可见区域的影响了。注意，一个应用程序窗口的可见区域只受位于它上面的其它应用程序窗口影响，而不会受到位于它下面的其它的应用程序窗口影响，因此，我们是按照从上到下的顺序（z-order）来计算系统中各个应用程序窗口的可见区域的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;为了方便描述，我们假设位于一个应用程序窗口上面的所有应用程序窗口组成了一个&lt;strong&gt;整体的可见区域（Above Covered Layers）&lt;/strong&gt;，并且这个可见区域与我们所要讨论的应用程序窗口相交，即它们叠加在一起，如图所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%E4%B8%80%29----%E5%90%88%E6%88%90Layer%E4%B9%8B%E5%87%86%E5%A4%87%E5%90%88%E6%88%90/cover.jpg&quot; alt=&quot;cover&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;由蓝色矩形组成的区域即为上层所有应用程序窗口所组成的一个&lt;strong&gt;整体可见区域&lt;/strong&gt;，这个整体可见区域与下面绿色矩形组成的一个应用程序窗口相交的部分，即由虚线所围成的区域，就是下面的一个应用程序窗口的&lt;strong&gt;被覆盖区域&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;一个应用程序窗口的&lt;strong&gt;被覆盖区域&lt;/strong&gt;有可能是半透明的，也有可能是完全不透明的，但是不可能是透明的，如图所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%E4%B8%80%29----%E5%90%88%E6%88%90Layer%E4%B9%8B%E5%87%86%E5%A4%87%E5%90%88%E6%88%90/coveropaque.jpg&quot; alt=&quot;coveropaque&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在原来由虚线围成的区域中，深蓝色的那部分区域就是&lt;strong&gt;完全不透明的（Above Opaque  Layers）&lt;/strong&gt;，这时候由绿色矩形组成的应用程序窗口的可见区域除了要减去中间的洞（&lt;strong&gt;透明区域&lt;/strong&gt;）之外，还要减去&lt;strong&gt;被覆盖的完全不透明区域&lt;/strong&gt;，如下图所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%E4%B8%80%29----%E5%90%88%E6%88%90Layer%E4%B9%8B%E5%87%86%E5%A4%87%E5%90%88%E6%88%90/covertransparent.jpg&quot; alt=&quot;covertransparent&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从上面的讨论我们就可以清楚地知道，为了计算一个应用程序窗口的最终可见区域，我们需要知道：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;应用程序窗口的左上角位置，以及宽度和高度，以便可以获得应用程序窗口的&lt;strong&gt;原始可见区域&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;应用程序窗口的&lt;strong&gt;透明区域&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;应用程序窗口的&lt;strong&gt;被覆盖完全不透明区域&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;用第1步到的原始可见区域减去第2步的透明区域和第3步的被覆盖完全不透明区域，就可以得到一个应用程序窗口的最终可见区域。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;为了获得第3步的被覆盖完全不透明区域，我们在计算一个应用程序窗口的最终可见区域的过程中，还需要将此前得到的应用程序窗口的完全不透明区域组合起来，形成一个&lt;strong&gt;覆盖完全不透明区域（Above Opaque  Layers）&lt;/strong&gt;，因此，我们还需要知道：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;应用程序窗口的&lt;strong&gt;完全不透明区域&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;此外，由于一个应用程序窗口的被覆盖半透明区域是需要与上层的应用程序窗口可见区域执行混合计算的，因此，我们在计算系统中各个应用程序窗口的可见区域的过程中，&lt;strong&gt;还需要将所有上层的应用程序窗口可见区域组合起来形成一个覆盖区域（Above Covered Layers）&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以计算所有Layer的可见区域逻辑， 按照Z-order逐个计算各layer的可见区域。对于Z-order值最大的layer，显然没有其它图层会遮盖它。所以它的可见区域(visibleRegion)应该是(当然，前提是这个layer没有超过屏幕区域)自身的大小再减去完全透明的部分(transparentRegion)，由此计算出来的结果我们把它称为aboveCoveredLayers。这个变量应该是全局的，因为它需要被传递到后面的layers中，然后不断地累积运算，直到覆盖整个屏幕区域。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;有了这些背景知识之后，接下来我们就可以分析SurfaceFlinger类的成员函数computeVisibleRegions的实现了。&lt;/p&gt;
&lt;h3 id=&quot;computeVisibleRegions&quot;&gt;&lt;a href=&quot;#computeVisibleRegions&quot; class=&quot;headerlink&quot; title=&quot;computeVisibleRegions&quot;&gt;&lt;/a&gt;computeVisibleRegions&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;computeVisibleRegions代码有点长，我们分段阅读：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::computeVisibleRegions(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; LayerVector&amp;amp; currentLayers, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; layerStack,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Region&amp;amp; outDirtyRegion, Region&amp;amp; outOpaqueRegion)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Region aboveOpaqueLayers;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Region aboveCoveredLayers;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Region dirty;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    outDirtyRegion.clear();&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这段代码定义了另外两个区域aboveOpaqueLayers，分别用来描述上层&lt;strong&gt;覆盖完全不透明区域（Above Opaque  Layers）&lt;/strong&gt;和&lt;strong&gt;上层覆盖区域（Above Covered Layers）&lt;/strong&gt;，上面讲过，这两个计算累加的结果。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; 我们接着往下阅读代码：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;size_t i = currentLayers.size();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    while (i--) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const sp&amp;lt;Layer&amp;gt;&amp;amp; layer = currentLayers[i];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // start with the whole surface at its current location&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const Layer::State&amp;amp; s(layer-&amp;gt;getDrawingState());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // only consider the layers on the given layer stack&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (s.layerStack != layerStack)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            continue;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这段代码是一个while循环的前面几行。系统中所有需要计算可见区域的应用程序窗口都保存在参数currentLayers所描述的一个向量中。这段代码的while循环就是用来逐个地这些应用程序窗口的可见区域的。注意，&lt;strong&gt;这个while是先计算是按照从上到下的顺序来计算系统中各个应用程序窗口的可见区域的&lt;/strong&gt;。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后获得用来描述当前正在处理的应用程序窗口的当前渲染状态的一个State对象s，然后判断是否是当前应用程序的layerStack，否则就continue。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们继续往下阅读代码：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * opaqueRegion: area of a surface that is fully opaque.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Region opaqueRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * visibleRegion: area of a surface that is visible on screen&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * and not fully transparent. This is essentially the layer&#39;s&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * footprint minus the opaque regions above it.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * Areas covered by a translucent surface are considered visible.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Region visibleRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * coveredRegion: area of a surface that is covered by all&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * visible regions above it (which includes the translucent areas).&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Region coveredRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * transparentRegion: area of a surface that is hinted to be completely&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * transparent. This is only used to tell when the layer has no visible&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * non-transparent regions and can be removed from the layer list. It&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * does not affect the visibleRegion of this layer or any layers&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * beneath it. The hint may not be correct if apps don&#39;t respect the&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * SurfaceView restrictions (which, sadly, some don&#39;t).&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Region transparentRegion;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接着再定义了四个Region对象opaqueRegion、visibleRegion、coveredRegion和transparentRegion，分别用来描述当前正在处理的应用程序窗口的&lt;strong&gt;完全不透明区域、可见区域、被覆盖区域和透明区域&lt;/strong&gt;。这四个区域的含义和作用如前所述。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;go on:&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;// handle hidden surfaces by setting the visible region to empty&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       if (CC_LIKELY(layer-&amp;gt;isVisible())) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           //是否是半透明&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           const bool translucent = !layer-&amp;gt;isOpaque(s);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           //layer的可见区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           Rect bounds(s.transform.transform(layer-&amp;gt;computeBounds()));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           //以便可以得到当前正在处理的应用程序窗口的初始可见区域visibleRegion&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           visibleRegion.set(bounds);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           if (!visibleRegion.isEmpty()) &amp;#123;//计算透明区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;               // Remove the transparent area from the visible region&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;               if (translucent) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                   //当前渲染状态的一个State对象s的成员变量transform指向的也是一个变换矩阵&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                   //用来描述当前正在处理的应用程序窗口的位置、旋转方向和缩放因子等&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                   const Transform tr(s.transform);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                   //函数接着判断当前正在处理的应用程序窗口是否被旋转过或者被缩放过&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                   if (tr.transformed()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                       //判断当前正在处理的应用程序窗口是否被旋转和缩放得不规则&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                       if (tr.preserveRects()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                           // transform the transparent region&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                           transparentRegion = tr.transform(s.activeTransparentRegion);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                       &amp;#125; else &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                           //即当当前正在处理的应用程序窗口被旋转和缩放得不规则时，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                           //这时候对应用程序窗口的透明区域进行旋转或者缩放就会很复杂，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                           //于是函数就干脆将它的透明区域忽略掉&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                           // transformation too complex, can&#39;t do the&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                           // transparent region optimization.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                           transparentRegion.clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                       &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                   &amp;#125; else &amp;#123;//如果没有经过矩阵变换处理&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                       transparentRegion = s.activeTransparentRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                   &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;               &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;               // compute the opaque region&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;               //当当前正在处理的应用程序窗口是完全不透明，并且旋转方向也是规则时，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;               //那么它的完全不透明区域opaqueRegion就等于前面计算所得到的可见区域visibleRegion&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;               const int32_t layerOrientation = s.transform.getOrientation();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;               if (s.alpha==255 &amp;amp;&amp;amp; !translucent &amp;amp;&amp;amp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                       ((layerOrientation &amp;amp; Transform::ROT_INVALID) == false)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                   // the opaque region is the layer&#39;s footprint&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                   opaqueRegion = visibleRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;               &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这段代码用来计算当前正在处理的应用程序窗口的可见区域和完全不透明区域。只有在当前正在处理的应用程序窗口处于可见状态，并且它不是完全透明时，才需要计算这两个区域。我们看看Layer的isVisible函数，位于frameworks/native/services/surfaceflinger/Layer.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; Layer::isVisible() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Layer::&lt;span class=&quot;function&quot;&gt;State&amp;amp; &lt;span class=&quot;title&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mDrawingState)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; !(s.flags &amp;amp; &lt;span class=&quot;keyword&quot;&gt;layer_state_t&lt;/span&gt;::eLayerHidden) &amp;amp;&amp;amp; s.alpha&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;amp;&amp;amp; (mActiveBuffer != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt; || mSidebandStream != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当State对象s的成员变量flags的ISurfaceComposer::eLayerHidden位等于0时，就说明当前正在处理的应用程序窗口是处于可见状态的，而当它的另外一个成员变量alpha的值不等于0的时候，就说明当前正在处理的应用程序窗口不是完全透明的。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;回到上面部分，接着计算透明区域。用来描述当前正在处理的应用程序窗口的当前渲染状态的一个State对象s的成员变量transform指向的也是一个变换矩阵，用来描述当前正在处理的应用程序窗口的位置、旋转方向和缩放因子等。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数接着判断当前正在处理的应用程序窗口是否被旋转过或者被缩放过。如果是的话，那么前面调用变换矩阵tr的成员函数transformed的返回值就会等于true，即变量transformed的等于true。在这种情况下，函数就要相应地对当前正在处理的应用程序窗口的透明区域进行旋转或者缩放。&lt;strong&gt;但是有一种特殊情况，即当当前正在处理的应用程序窗口被旋转和缩放得不规则时，这时候对应用程序窗口的透明区域进行旋转或者缩放就会很复杂，于是函数就干脆将它的透明区域忽略掉。&lt;/strong&gt;判断当前正在处理的应用程序窗口是否被旋转和缩放得不规则是通过调用变换矩阵tr的成员函数preserveRects来实现的，当它的返回值等于true的时候，就说明当前正在处理的应用程序窗口是否被旋转和缩放之后还是规则，否则就是不规则的。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当前正在处理的应用程序窗口的透明区域保存在State对象s的成员变量transparentRegion中，按照上述原理，函数按照以下规则来对它进行处理：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）当变量transformed的等于false时，说明当前正在处理的应用程序窗口的透明区域就不需要进行旋转或者缩放，这时候就可以将这个透明区域保存在变量transparentRegionScreen中。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）当变量transformed的等于true，并且变换矩阵tr的成员函数preserveRects的返回值也等于true时，那么就说明当前正在处理的应用程序窗口的透明区域需要进行旋转或者缩放，这时候通过调用变换矩阵tr的成员函数transform来实现的。 最终得到的透明区域同样是保存在变量transparentRegionScreen中。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3） 当变量transformed的等于true，并且变换矩阵tr的成员函数preserveRects的返回值等于false时，那么就说明需要忽略掉当前正在处理的应用程序窗口的透明区域，通过成员函数clear来实现的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们接着来看当前正在处理的应用程序窗口的完全不透明区域的计算过程。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当当前正在处理的应用程序窗口是完全不透明，并且旋转方向也是规则时，那么它的完全不透明区域opaqueRegion就等于前面计算所得到的可见区域visibleRegion。当当前正在处理的应用程序窗口的Alpha通道等于255，即当State对象s的成员变量alpha的值等于255，并且变量translucent的值等于false时，就说明它是完全不透明的，而当当前正在处理的应用程序窗口的旋转方向layerOrientation的Transform::ROT_INVALID位等于0的时候，就说明它的旋转方向是规则的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;go on：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// Clip the covered region to the visible region&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        coveredRegion = aboveCoveredLayers.intersect(visibleRegion);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Update aboveCoveredLayers for next (lower) layer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        aboveCoveredLayers.orSelf(visibleRegion);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// subtract the opaque region covered by the layers above us&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        visibleRegion.subtractSelf(aboveOpaqueLayers);&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这段代码用来计算当前正在处理的应用程序窗口的被覆盖区域，以及再进一步计算它的可见区域，主要考虑是否被上层的不透明区域覆盖了。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;变量aboveCoveredLayers用来描述当前正在处理的应用程序窗口的所有上层应用程序窗口所组成的可见区域，将这个区域与当前正在处理的应用程序窗口的可见区域visibleRegion相交，就可以得到当前正在处理的应用程序窗口的被覆盖区域coveredRegion，而将这个区域与当前正在处理的应用程序窗口的可见区域visibleRegion相或一下，就可以得到下一个应用程序窗口的所有上层应用程序窗口所组成的可见区域aboveCoveredLayers。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;变量aboveOpaqueLayers用来描述当前正在处理的应用程序窗口的所有上层应用程序窗口所组成的完全不透明区域，这个区域从当前正在处理的应用程序窗口的可见区域visibleRegion减去后，就可以得到当前正在处理的应用程序窗口的最终可见区域visibleRegion。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;go on:&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// compute this layer&#39;s dirty region&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (layer-&amp;gt;contentDirty) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           &lt;span class=&quot;comment&quot;&gt;// we need to invalidate the whole region&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           dirty = visibleRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           &lt;span class=&quot;comment&quot;&gt;// as well, as the old visible region&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           dirty.orSelf(layer-&amp;gt;visibleRegion);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           layer-&amp;gt;contentDirty = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           &lt;span class=&quot;comment&quot;&gt;/* compute the exposed region:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            *   the exposed region consists of two components:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            *   1) what&#39;s VISIBLE now and was COVERED before&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            *   2) what&#39;s EXPOSED now less what was EXPOSED before&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            *&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            * note that (1) is conservative, we start with the whole&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            * visible region but only keep what used to be covered by&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            * something -- which mean it may have been exposed.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            *&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            * (2) handles areas that were not covered by anything but got&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            * exposed because of a resize.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Region newExposed = visibleRegion - coveredRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Region oldVisibleRegion = layer-&amp;gt;visibleRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Region oldCoveredRegion = layer-&amp;gt;coveredRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Region oldExposed = oldVisibleRegion - oldCoveredRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           dirty = (visibleRegion&amp;amp;oldCoveredRegion) | (newExposed-oldExposed);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       dirty.subtractSelf(aboveOpaqueLayers);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       &lt;span class=&quot;comment&quot;&gt;// accumulate to the screen dirty region&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       outDirtyRegion.orSelf(dirty);&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这段代码用来计算屏幕的脏区域。我们首先解释一下屏幕的脏区域是如何计算的。将所有应用程序窗口的脏区域都组合起来，就可以得到屏幕的脏区域，这个脏区域就是需要重新执行渲染操作的。因此，为了得到屏幕的脏区域，我们要知道当前正在处理的应用程序窗口的脏区域，以及之前已经处理了的应用程序窗口脏区域组合。前者使用变量dirty来描述，而后者使用输出参数outDirtyRegion来描述。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们首先来看当前正在处理的应用程序窗口的脏区域dirty是如何计算的。我们分两种情况来考虑。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）首先考虑当前正在处理的应用程序窗口上一次的状态还未来得及处理的情况，即它当前的内容是脏的。在这种情况下，layer的成员变量contentDirty的值就会等于true。这时候我们就需要将该应用程序窗口的上一次可见区域，以及当前的可见区域合并起来，形成一个大的脏区域，这样就可以将两次渲染操作合并成一次来执行。当前正在处理的应用程序窗口的上一次可见区域保存在layer的成员变量visibleRegion中，而它前的可见区域保存在变量visibleRegion中。将这两者相或一下，就可以得到当前正在处理的应用程序窗口的脏区域dirty。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）接着考虑当前正在处理的应用程序窗口上一次的状态已经处理了的情况，即它当前的内容不是脏的，这意味着它所要显示的内容没有发生变化。在这种情况下，就不需要重新渲染所有的可见区域。那么那些区域是需要重新渲染的呢？第一部分区域是之前是被覆盖的，现在不被覆盖了，第二部分是由于窗口大小变化而引发的新增不被覆盖区域。接下来，我们就来看看这两部分区域是如何计算的。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;将一个应用程序窗口的当前可见区域减去被覆盖区域，就可以它的当前不被覆盖的区域newExposed，按照同样的方法，我们可以也可以得到它的上一次不被覆盖的区域oldExposed。注意，一个应用程序窗口的上一次可见区域和被覆盖区域分别保存与它相对应的一个Layer对象的成员变量visibleRegion和coveredRegion中。这样，将一个应用程序窗口的当前不被覆盖的区域newExposed减去它的上一次不被覆盖的区域oldExposed，就可以得到新增的不被覆盖区域，即可以得到第二部分需要重新渲染的区域。另一方面，将一个应用程序窗口的当前可见区域visibleRegion与它的上一次被覆盖区域oldCoveredRegion相交，就可以得到之前是被覆盖的而现在不被覆盖了的区域，即可以得到第一部分需要重新渲染的区域。将第一部分和第二部分需要重新渲染的区域组合起来，就可以得到当前正在处理的应用程序窗口的脏区域dirty。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;得到了当前正在处理的应用程序窗口的脏区域dirty，接下来的事情就好办了。首先从该脏区域dirty减去上层的完全不透明区域，因为后者的渲染不需要当前应用程序窗口来参与，接着最将得到的新的脏区域dirty累加到输出参数outDirtyRegion中去，这样就可以得到目前为止，SurfaceFlinger服务需要渲染的脏区域。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;go on:&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;// Update aboveOpaqueLayers for next (lower) layer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        aboveOpaqueLayers.orSelf(opaqueRegion);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Store the visible region in screen space&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        layer-&amp;gt;setVisibleRegion(visibleRegion);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        layer-&amp;gt;setCoveredRegion(coveredRegion);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        layer-&amp;gt;setVisibleNonTransparentRegion(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                visibleRegion.subtract(transparentRegion));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    outOpaqueRegion = aboveOpaqueLayers;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这段代码是前面的while循环的几行结束代码，主要用来做三件事情。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;第一件事情是计算到目前为止所得到的上层应用程序窗口的完全不透明区域，这是通过组合当前正在处理的应用程序窗口的完全不透明区域与位于它上面的的所有应用程序窗口的完全不透明区域aboveOpaqueLayers来得到的，并且最终结果保存在变量aboveOpaqueLayers中。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;第二件事情是调用layer的成员函数setVisibleRegion、setCoveredRegion和setVisibleNonTransparentRegion来保存当前正在处理的应用程序窗口的可见区域、被覆盖区域和没有透明区域的可见区域。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;第三件事情是，函数还将前面所有的应用程序窗口组成的完全不透明区域aboveOpaqueLayers保存在输出参数opaqueRegion，以便可以返回给调用者使用。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这就是计算Layer可视区域的所有流程，只要理解了里面每个变量代表对应含义区域的意义，就不难分析。这里我们rebuildLayerStacks流程就分析完了。我们继续往下走，分析下一步。&lt;/p&gt;
&lt;h2 id=&quot;setUpHWComposer&quot;&gt;&lt;a href=&quot;#setUpHWComposer&quot; class=&quot;headerlink&quot; title=&quot;setUpHWComposer&quot;&gt;&lt;/a&gt;setUpHWComposer&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;合成步骤的下一步就是setUpHWComposer函数调用，配置硬件合成器。&lt;/p&gt;
&lt;h3 id=&quot;回顾HWC&quot;&gt;&lt;a href=&quot;#回顾HWC&quot; class=&quot;headerlink&quot; title=&quot;回顾HWC&quot;&gt;&lt;/a&gt;回顾HWC&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们之前在&lt;a href=&quot;http://windrunnerlihuan.com/2017/04/27/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%BA%8C-SurfaceFlinger%E6%A6%82%E8%BF%B0/&quot;&gt;Android SurfaceFlinger 学习之路(二)—-SurfaceFlinger概述&lt;/a&gt;讲过，用于合成surface的功能模块可以有2个，OpenGL ES &amp;amp; HWC，它的管理实在HWC里面实现的。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;官网也给出了一些解释，&lt;a href=&quot;https://source.android.google.cn/devices/graphics/arch-sf-hwc&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;https://source.android.google.cn/devices/graphics/arch-sf-hwc&lt;/a&gt; ，不过中文翻译的不是很好，最好看看英文：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Hardware Composer HAL (HWC) 是在 Android 3.0 中推出的，并且多年来一直都在不断演进。它主要是用来确定通过可用硬件来合成缓冲区的最有效方法。作为 HAL，其实现是特定于设备的，而且通常由显示设备硬件原始设备制造商 (OEM) 完成。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当考虑叠加平面时，很容易发现这种方法的好处。它的目的是在显示硬件（而不是 GPU）中将多个缓冲区合成在一起。例如，假设有一部处于纵向模式的普通 Android 手机，其状态栏在顶部，导航栏在底部，其他地方为应用内容。每个层的内容都在单独的缓冲区中。您可以使用以下任一方法处理合成：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;将应用内容渲染到暂存缓冲区中，然后在其上渲染状态栏，再在其上渲染导航栏，最后将暂存缓冲区传送到显示硬件。&lt;/li&gt;
&lt;li&gt;将三个缓冲区全部传送到显示硬件，并告知它从不同的缓冲区读取屏幕不同部分的数据。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;后一种方法可以显著提高效率。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面两种合成分别叫&lt;strong&gt;离线合成&lt;/strong&gt;和&lt;strong&gt;在线合成&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%E4%B8%80%29----%E5%90%88%E6%88%90Layer%E4%B9%8B%E5%87%86%E5%A4%87%E5%90%88%E6%88%90/offlineandonline.jpg&quot; alt=&quot;offlineandonline&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;离线合成：先将所有图层画到一个最终层（FrameBuffer）上，再将FrameBuffer送到LCD显示。由于合成FrameBuffer与送LCD显示一般是异步的（线下生成FrameBuffer，需要时线上的LCD去取），因此叫离线合成。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在线合成：不使用FrameBuffer，在LCD需要显示某一行的像素时，用显示控制器将所有图层与该行相关的数据取出，合成一行像素送过去。只有一个图层时，又叫Overlay技术。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;由于省去合成FrameBuffer时读图层，写FrameBuffer的步骤，大幅降低了内存传输量，减少了功耗，但这个需要硬件支持。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;效率对比：大部分情况下，在线合成比起离线合成有很明显的优势，大幅降低了内存带宽的消耗。不过对于多屏显示，静态场景（仅限LCD不带缓存的情况），离线合成会有优势，做下简单的计算不难推得。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;显示处理器功能差异很大。overlay的数量（无论层是否可以旋转或混合）以及对定位和叠加的限制很难通过 API 表达。HWC 会尝试通过一系列决策来适应这种多样性：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;SurfaceFlinger给HWC提供layer list，询问如何处理这些layer；&lt;/li&gt;
&lt;li&gt;HWC将每个layer标记为overlay或者GLES composition，然后回馈给SurfaceFlinger；&lt;/li&gt;
&lt;li&gt;SurfaceFlinger需要去处理那些GLES的合成，而不用去管overlay的合成，最后将overlay的layer和GLES合成后的buffer发送给HWC处理。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;用之前一幅图表示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%E4%B8%80%29----%E5%90%88%E6%88%90Layer%E4%B9%8B%E5%87%86%E5%A4%87%E5%90%88%E6%88%90/hwc.png&quot; alt=&quot;hwc&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;屏幕上的内容没有变化时，overlay的效率可能会低于 GL 合成。当overlay内容具有透明像素且overlay混合在一起时，尤其如此。在此类情况下，HWC 可以选择为部分或全部层请求 GLES 合成，并保留合成的缓冲区。如果 SurfaceFlinger 返回要求合成同一组缓冲区，HWC 可以继续显示先前合成的暂存缓冲区。这可以延长闲置设备的电池续航时间。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;运行 Android 4.4 或更高版本的设备通常支持 4 个overlay。尝试合成多于overlay的层会导致系统对其中一些层使用 GLES 合成，这意味着应用使用的层数会对功耗和性能产生重大影响。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;关于HWC HAL有更详细的解释，官网在置如此：&lt;a href=&quot;https://source.android.google.cn/devices/graphics/implement-hwc&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;https://source.android.google.cn/devices/graphics/implement-hwc&lt;/a&gt; ，中文翻译的依旧有些别扭：&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Hardware Composer HAL (HWC) 由 SurfaceFlinger 用来将 Surface 合成到屏幕。HWC 可以抽象出叠加层和 2D 位块传送器等对象，有助于分载通常使用 OpenGL 完成的一些工作。&lt;br&gt;Android 7.0 包含新版本的 HWC (HWC2)，由 SurfaceFlinger 用来与专门的窗口合成硬件进行通信。SurfaceFlinger 包含使用 3D 图形处理器 (GPU) 执行窗口合成任务的备用路径，但由于以下几个原因，此路径并不理想：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;通常，GPU 未针对此用例进行过优化，因此能耗可能要大于执行合成所需的能耗。&lt;/li&gt;
&lt;li&gt;每次 SurfaceFlinger 使用 GPU 进行合成时，应用都无法使用处理器进行自我渲染，因此应尽可能使用专门的硬件而不是 GPU 进行合成。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;由于 Hardware Composer 抽象层后的物理显示设备硬件可因设备而异，因此很难就具体功能提供建议。一般来说，请遵循以下准则：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HWC 应至少支持 4 个叠加层（状态栏、系统栏、应用和壁纸/背景）。&lt;/li&gt;
&lt;li&gt;层可以大于屏幕，因此 HWC 应能处理大于显示屏的层（例如壁纸）。&lt;/li&gt;
&lt;li&gt;应同时支持预乘每像素 Alpha 混合和每平面 Alpha 混合。&lt;/li&gt;
&lt;li&gt;HWC 应能消耗 GPU、相机和视频解码器生成的相同缓冲区，因此支持以下某些属性很有帮助：&lt;ul&gt;
&lt;li&gt;RGBA 打包顺序&lt;/li&gt;
&lt;li&gt;YUV 格式&lt;/li&gt;
&lt;li&gt;平铺、重排和步幅属性&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;为了支持受保护的内容，必须提供受保护视频播放的硬件路径。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;常规建议是首先实现非运行的 HWC；在结构完成后，实现一个简单的算法，以将合成委托给 HWC（例如，仅将前 3 个或前 4 个 Surface 委托给 HWC 的叠加硬件）。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;专注于优化，例如智能地选择要发送到叠加硬件的 Surface，以最大限度提高从 GPU 移除的负载。另一种优化是检测屏幕是否正在更新；如果不是，则将合成委托给 OpenGL 而不是 HWC，以节省电量。当屏幕再次更新时，继续将合成分载到 HWC。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;为常见用例做准备，如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;纵向和横向模式下的全屏游戏&lt;/li&gt;
&lt;li&gt;带有字幕和播放控件的全屏视频&lt;/li&gt;
&lt;li&gt;主屏幕（合成状态栏、系统栏、应用窗口和动态壁纸）&lt;/li&gt;
&lt;li&gt;受保护的视频播放&lt;/li&gt;
&lt;li&gt;多显示设备支持&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这些用例应针对常规可预测的用途，而不是很少遇到的边缘用例（否则，优化将收效甚微）。实现必须平衡动画流畅性和交互延迟时间这两个相互矛盾的目标。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;根据这些Google定义的这些准则，我们能够更好地分析配置硬件合成器的步骤。&lt;/p&gt;
&lt;h3 id=&quot;准备工作&quot;&gt;&lt;a href=&quot;#准备工作&quot; class=&quot;headerlink&quot; title=&quot;准备工作&quot;&gt;&lt;/a&gt;准备工作&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在分析setUpHWComposer函数之前，我们要回顾一下&lt;a href=&quot;http://windrunnerlihuan.com/2017/05/25/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%BA%94-VSync-%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/&quot;&gt;Android SurfaceFlinger 学习之路(五)—-VSync 工作原理&lt;/a&gt;中的&lt;code&gt;硬件加载&lt;/code&gt;的部分，初始化&lt;strong&gt;显示设备&lt;/strong&gt;和&lt;strong&gt;HWComposer设备&lt;/strong&gt;的内容。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从上一部分得知，比如使用3D合成，需要大面积的像素混合计算和大量的内存传输（GPU读写GraphicBuffer所需），对GPU和DDR来说是一个巨大的负担。在GPU/DDR重度使用的场景（比如玩游戏），会造成发热、卡顿等。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;为了提升性能，减少功耗，可以将合成这个过程交由另一个芯片完成，减轻GPU负担。进一步，直接让这个芯片连LCD，在LCD需要显示某一行时在线合成。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;HwComposer便是这一个/多个专用合成芯片的驱动HAL层。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;驱动由集成芯片系统的厂商自行设计，但需要遵循一定的标准，这个标准就是Android规定的HwComposer接口。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;hwcomposer的接口定义位于此文件：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;hardware/libhardware/include/hardware/hwcomposer.h&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;其中部分宏定义在：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;hardware/libhardware/include/hardware/hwcomposer_defs.h&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;相关结构解释如下：&lt;/p&gt;
&lt;h4 id=&quot;Layer&quot;&gt;&lt;a href=&quot;#Layer&quot; class=&quot;headerlink&quot; title=&quot;Layer&quot;&gt;&lt;/a&gt;Layer&lt;/h4&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在SurfaceFlinger中，Layer对应于window表示一个Buffer循环体系，对HwComposer而言，Layer仅指代当前Buffer，也即SurfaceFlinger中的Layer的当前帧。&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; hwc_layer_1 &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; compositionType;&lt;span class=&quot;comment&quot;&gt;//合成类型，SurfaceFlinger将合成目标Framebuffer的合成类型设为HWC_FRAMEBUFFER_TARGET，其他hwcomposer在prepare时根据实际情况修改&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//在(*prepare)()调用前，需要复位HWC_BACKGROUND or HWC_FRAMEBUFFER，需要设置HWC_GEOMETRY_CHANGED的标志符，并在(*prepare)()过程中保持，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * HWC_BACKGROUND：(*prepare)()调用前设置，表明这是个特殊的&quot;background&quot;的层，backgroundColor是无效的，HWC向HWC_FRAMEBUFFER切换此值，并表示无法使用backgroundColor。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * HWC_FRAMEBUFFER_TARGET：在prepare前设置此值，此值表明此层是framebuffersurface层，作为OpenGLEScomposition的对象，如果HWC设置其他层为HWC_OVERLAY或则为HWC_BACKGROUND，则在set（）过程中opengles则什么都不干。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * 此标志仅仅用在版本至少为HWC_DEVICE_API_VERSION_1_1，在老版本的过程中，OpenGLES target 与（dpy, sur)通信，在HWC实现的过程中此值不能设置。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * 该Layer是3D合成的目标Layer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * HWC_FRAMEBUFFER：在(*prepare)()调用前设置，仅仅在HWC_GEOMETRY_CHANGED flag 也在设置的时候设置，并表明此层将使用opengles画进framebuffer中。HWC可以切换此值到HWC_OVERLAY表明其将要管理此层。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * hwcomposer无法处理此Layer，该Layer需要走3D合成流程，用OpenGL绘制&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * HWC_OVERLAY：在(*prepare)()过程中，通过HWC设置，表明此层由HWC设置，不能通过OpenGLES 合成。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * 该Layer为硬件合成器所处理，不需要OpenGLES去渲染&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * HWC_SIDEBAND：在(*prepare)()前设置，此值表明此层的内容来自于边带视频流，此流在适当的时间（去同步多媒体流），与其他层当前内容进行合成，显示结果图片。此现象依赖于正常的prepare/set周期。prepare/set调用仅仅发生在其他层的改变，或则是边带视频流的位置或则大小的改变。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;假如h/w composer 无法管理层由于边带视频流的原因（unsupportedscaling/blending/rotation, or too many sideband layers)，其可以在(*prepare)()设置合成类型为HWC_FRAMEBUFFER。但是，这样做显示维实体颜色，因为平台无法使用GPU进行合成边带视频层。这个问题在未来的平台版本中将得到改善。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * 该Layer为视频的边频带，需要硬件合成器作特殊处理，若不支持，OpenGL方式只能以一个色块替代，这个标志是外界（应用/驱动）调用窗口系统的perform方法配置的&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * HWC_CURSOR_OVERLAY：在(*prepare)()期间，设置HWC实现，这个值意味着此层的合成将要被HWC的管理，另外，客户端在屏幕上可以异步刷新，这个层的位置可以使用setCursorPositionAsync() api。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * 该Layer可通过setCursorPositionAsync 方法改变坐标&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; hints;&lt;span class=&quot;comment&quot;&gt;//hwcomposer设置，通知SurfaceFlinger需要修改的配置&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    HWC_HINT_TRIPLE_BUFFER  = 0x00000001：表示需要SurfaceFlinger将此Layer改成3Buffer循环&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    HWC_HINT_CLEAR_FB       = 0x00000002：要求SurfaceFlinger清空该Layer位置的FrameBuffer数据（即置0）&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags;&lt;span class=&quot;comment&quot;&gt;//SurfaceFlinger设置，hwcomposer作处理&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    HWC_SKIP_LAYER = 0x00000001：此Layer不参与合成，应当忽略&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    HWC_IS_CURSOR_LAYER = 0x00000002：此Layer建议设定为一个CURSOR_LAYER，hwcomposer能处理的话将其合成类型改为HWC_CURSOR_OVERLAY&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*该Layer的颜色/Buffer信息*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;union&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;hwc_color_t&lt;/span&gt; backgroundColor;&lt;span class=&quot;comment&quot;&gt;//背景颜色，适用于纯色Layer，hwc_color_t 为一个 argb 结构体&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;union&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt; handle;&lt;span class=&quot;comment&quot;&gt;//此即之间提到的GraphicBuffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;native_handle_t&lt;/span&gt;* sidebandStream;&lt;span class=&quot;comment&quot;&gt;//HWC_SIDEBAND类型Layer的buffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; transform;&lt;span class=&quot;comment&quot;&gt;//该Layer所需要作的变换，具体为：&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        HWC_TRANSFORM_FLIP_H = HAL_TRANSFORM_FLIP_H//水平翻转&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        HWC_TRANSFORM_FLIP_V = HAL_TRANSFORM_FLIP_V//垂直翻转&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        HWC_TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90,//需要旋转90度&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        HWC_TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180,//需要旋转180度&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        HWC_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270,//需要旋转270度&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; blending;&lt;span class=&quot;comment&quot;&gt;//当前Layer绘制时，和底色/目标色的混合方式&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//HWC_BLENDING_NONE = 0x100：不混合，直接覆盖&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//HWC_BLENDING_PREMULT = 0x105：该Layer的颜色已经做过alpha预乘，因此混合方式为 src + (1-src.a)*dst&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//HWC_BLENDING_COVERAGE = 0x405：该Layer的颜色未做过预乘，按 src.a * src + (1-src.a) * dst 的方式混合&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;union&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// crop rectangle in integer (pre HWC_DEVICE_API_VERSION_1_3)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;hwc_rect_t&lt;/span&gt; sourceCropi;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;hwc_rect_t&lt;/span&gt; sourceCrop; &lt;span class=&quot;comment&quot;&gt;// just for source compatibility&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// crop rectangle in floats (as of HWC_DEVICE_API_VERSION_1_3)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;hwc_frect_t&lt;/span&gt; sourceCropf;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;;&lt;span class=&quot;comment&quot;&gt;//该Layer取哪一个区域进行合成&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;hwc_rect_t&lt;/span&gt; displayFrame;&lt;span class=&quot;comment&quot;&gt;//该Layer合成的目标区域&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;hwc_region_t&lt;/span&gt; visibleRegionScreen;&lt;span class=&quot;comment&quot;&gt;//该Layer的可见区域，该区域必然是displayFrame的子集。这个区域由SurfaceFlinger计算而得，用于提示hwcomposer不去合成该Layer的不可见区域，hwcomposer中应当以这个为基准，对应计算该Layer相应的sourcecrop。&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; acquireFenceFd;&lt;span class=&quot;comment&quot;&gt;//由Buffer生产者创建，SurfaceFlinger传递进来，hwcomposer在使用该Layer的Buffer之前，需要等这个fence&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; releaseFenceFd;&lt;span class=&quot;comment&quot;&gt;//由hwcomposer创建，生产者在使用该Buffer之前需要等此fence&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;uint8_t&lt;/span&gt; planeAlpha;&lt;span class=&quot;comment&quot;&gt;//整个Layer的alpha值，在取Layer的像素作运算之前，需要先乘 planeAlpha/255。&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;/* Pad to 32 bits */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;uint8_t&lt;/span&gt; _pad[&lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;];&lt;span class=&quot;comment&quot;&gt;//用于结构体对齐，占位用&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;hwc_region_t&lt;/span&gt; surfaceDamage;&lt;span class=&quot;comment&quot;&gt;//记录相对上一次合成而言，发生了改变的source区域&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//保留位，用于驱动层自行设计&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;ifdef&lt;/span&gt; __LP64__&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint8_t&lt;/span&gt; reserved[&lt;span class=&quot;number&quot;&gt;120&lt;/span&gt; - &lt;span class=&quot;number&quot;&gt;112&lt;/span&gt;];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;else&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint8_t&lt;/span&gt; reserved[&lt;span class=&quot;number&quot;&gt;96&lt;/span&gt; - &lt;span class=&quot;number&quot;&gt;84&lt;/span&gt;];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125; &lt;span class=&quot;keyword&quot;&gt;hwc_layer_1_t&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里面最难理解和最易出错的是 SourceCrop、DisplayFrame和VisibleRegion，在处理SOC上的显示问题时，这往往是首先考虑的因素： &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%E4%B8%80%29----%E5%90%88%E6%88%90Layer%E4%B9%8B%E5%87%86%E5%A4%87%E5%90%88%E6%88%90/sourcecrop.jpg&quot; alt=&quot;sourcecrop&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如图所示，该Layer的显示区域部分被L2完全挡住，source crop 为该Layer参与合成的范围，display frame 为该Layer合成的目标区域，visibleRegion为该Layer被挡住后，剩余的可见区域集。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里我用了我的渣渣小米5，在Home页面，然后进入调试模式，输入adb shell dumpsys SurfaceFlinger ： &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%E4%B8%80%29----%E5%90%88%E6%88%90Layer%E4%B9%8B%E5%87%86%E5%A4%87%E5%90%88%E6%88%90/SF.png&quot; alt=&quot;SF&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;截取出这段信息，这段信息是SurfaceFlinger告知硬件合成器如何进行合成的。&lt;strong&gt;最后一个FramebufferTarget是目标层，不算进去&lt;/strong&gt;，参与合成的图层是三个，分别是 :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;com.android.systemui.ImageWallpaper&lt;/li&gt;
&lt;li&gt;com.miui.home/com.miui.home.launcher.Launcher&lt;/li&gt;
&lt;li&gt;StatusBar&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;其他参数对比我们上面的hwc_layer_1_t结构体，就能理解这些参数的意义。&lt;/p&gt;
&lt;h4 id=&quot;Display&quot;&gt;&lt;a href=&quot;#Display&quot; class=&quot;headerlink&quot; title=&quot;Display&quot;&gt;&lt;/a&gt;Display&lt;/h4&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; hwc_display_contents_1 &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* hwcomposer设置，surfaceflinger去等的fence。对于物理屏(实际上是使用在线合成方式的物理屏），对于虚拟屏/离线合成，此fence在离线合成的目标buffer完成全部写入后解除。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; retireFenceFd;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;union&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;/* HWC_DEVICE_VERSION_1_0 使用，dpy和sur对应于EGLDisplay 和 EGLSurface&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;hwc_display_t&lt;/span&gt; dpy;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;hwc_surface_t&lt;/span&gt; sur;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;;&lt;span class=&quot;comment&quot;&gt;//HWC_DEVICE_VERSION_1_0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;/*HWC_DEVICE_VERSION_1_3 之后支持 hwcomposer合成多屏，这里是指虚拟屏的输出buffer和对应的fence*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt; outbuf;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; outbufAcquireFenceFd;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*合成该显示屏的所有Layer*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; numHwLayers;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;hwc_layer_1_t&lt;/span&gt; hwLayers[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125; &lt;span class=&quot;keyword&quot;&gt;hwc_display_contents_1_t&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;物理显示屏表示连接实际的显示仪器如LCD，目的是产生显示效果，可以使用在线合成。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;虚拟显示屏表示目的是合成一个Buffer，不需要理会这个Buffer后续如何产生显示效果，这时需要把所有图层合成到指定的Buffer上。这种情况下必须离线合成。典型场景是手机连WFD/hdmi，手机合成好的Buffer通过wifi/hdmi传输到电视上显示。&lt;/p&gt;
&lt;h4 id=&quot;Device&quot;&gt;&lt;a href=&quot;#Device&quot; class=&quot;headerlink&quot; title=&quot;Device&quot;&gt;&lt;/a&gt;Device&lt;/h4&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;最后是device的函数指针定义&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; hwc_composer_device_1 &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;hw_device_t&lt;/span&gt; common;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//这种方式相当于C语言的继承实现，理解为 hwc_composer_device_1 继承于 hw_device_t 就可以了。&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//hw_device_t 包含一个基本信息 version（版本号），下面会提到&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*对所有显示屏中所有Layer作合成准备（此时也可以开始发送合成的命令码下去，启动硬件合成，但不需要等待完成），hwcomposer需要正确汇报每个Layer的composetype，以告知SurfaceFlinger是否需要额外处理。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    version 为 1.0 的驱动，只支持一个显示屏&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    version 为 1.1 的驱动，只支持物理显示屏&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    version 为 1.3 及以上的驱动，支持物理和虚拟显示屏*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*prepare)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; hwc_composer_device_1 *dev,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; numDisplays, &lt;span class=&quot;keyword&quot;&gt;hwc_display_contents_1_t&lt;/span&gt;** displays);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*此方法将完成各个图层的合成与显示，等效于EGL标准里面的eglSwapBuffers，不过eglSwapBuffers是对OpenGL标准/GPU有效，此方法是对硬件合成器有效*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*&lt;span class=&quot;built_in&quot;&gt;set&lt;/span&gt;)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; hwc_composer_device_1 *dev,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; numDisplays, &lt;span class=&quot;keyword&quot;&gt;hwc_display_contents_1_t&lt;/span&gt;** displays);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*这个接口一般只用于开启hwcomposer的vsync，在线合成触发vsync的机制较离线合成的设计会麻烦一些*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*eventControl)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; hwc_composer_device_1* dev, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; disp,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; event, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; enabled);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//控制屏幕状态的方法&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;union&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;/* HWC 1.3及之前版本，采用 blank 方式，开关某个显示屏 */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*blank)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; hwc_composer_device_1* dev, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; disp, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; blank);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;/* HWC 1.4及之后，提供更精细的 setPowerMode ，支持显示屏以较低功耗（但不关）的状态显示*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*setPowerMode)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; hwc_composer_device_1* dev, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; disp,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; mode);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*查询Hwcomposer的信息*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*query)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; hwc_composer_device_1* dev, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; what, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;* value);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*注册&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    *invalidate：屏幕刷新时触发&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    *vsync：hwcomopser中的vsync事件产生时触发&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    *hotplug：显示屏连接/断开时触发&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    * 三个回调函数*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; (*registerProcs)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; hwc_composer_device_1* dev,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;hwc_procs_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* procs);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*打印信息，调试用*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; (*dump)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; hwc_composer_device_1* dev, &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; *buff, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; buff_len);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*获取显示屏配置、属性*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*getDisplayConfigs)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; hwc_composer_device_1* dev, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; disp,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;* configs, &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt;* numConfigs);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*getDisplayAttributes)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; hwc_composer_device_1* dev, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; disp,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; config, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;* attributes, &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt;* values);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*getActiveConfig)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; hwc_composer_device_1* dev, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; disp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*配置属性，index表示有效属性的编号*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*setActiveConfig)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; hwc_composer_device_1* dev, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; disp,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; index);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*更改游标层的坐标*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*setCursorPositionAsync)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; hwc_composer_device_1 *dev, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; disp, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; x_pos, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; y_pos);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*自行添加的保留函数*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;* reserved_proc[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125; &lt;span class=&quot;keyword&quot;&gt;hwc_composer_device_1_t&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h3 id=&quot;实现&quot;&gt;&lt;a href=&quot;#实现&quot; class=&quot;headerlink&quot; title=&quot;实现&quot;&gt;&lt;/a&gt;实现&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后我们看看setUpHWComposer的实现。这个函数有点长，但是每个步骤都比较清晰，我们分步骤查看：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::setUpHWComposer() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; dpy=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; dpy&amp;lt;mDisplays.size() ; dpy++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; dirty = !mDisplays[dpy]-&amp;gt;getDirtyRegion(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;).isEmpty();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; empty = mDisplays[dpy]-&amp;gt;getVisibleLayersSortedByZ().size() == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; wasEmpty = !mDisplays[dpy]-&amp;gt;lastCompositionHadVisibleLayers;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// If nothing has changed (!dirty), don&#39;t recompose.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// If something changed, but we don&#39;t currently have any visible layers,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//   and didn&#39;t when we last did a composition, then skip it this time.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// The second rule does two things:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// - When all layers are removed from a display, we&#39;ll emit one black&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//   frame, then nothing more until we get new layers.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// - When a display is created with a private layer stack, we won&#39;t&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//   emit any black frames until a layer is added to the layer stack.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果没有改变（！dirty），不重新合成&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果有变化，但是当前没有可见的layers，并且上次合成过，那么这次跳过&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//有两个规则如下：&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//1.当所有的layers从显示屏移除，我们发射一个黑的frame，在来到新的layer之前都是黑的&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//2.当一个显示屏被创建时候带着一个私有的layer栈，我们直到新的layer被添加到这个layer stack时，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//才发射黑的frame&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; mustRecompose = dirty &amp;amp;&amp;amp; !(empty &amp;amp;&amp;amp; wasEmpty);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGV_IF(mDisplays[dpy]-&amp;gt;getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;string&quot;&gt;&quot;dpy[%zu]: %s composition (%sdirty %sempty %swasEmpty)&quot;&lt;/span&gt;, dpy,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mustRecompose ? &lt;span class=&quot;string&quot;&gt;&quot;doing&quot;&lt;/span&gt; : &lt;span class=&quot;string&quot;&gt;&quot;skipping&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                dirty ? &lt;span class=&quot;string&quot;&gt;&quot;+&quot;&lt;/span&gt; : &lt;span class=&quot;string&quot;&gt;&quot;-&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                empty ? &lt;span class=&quot;string&quot;&gt;&quot;+&quot;&lt;/span&gt; : &lt;span class=&quot;string&quot;&gt;&quot;-&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                wasEmpty ? &lt;span class=&quot;string&quot;&gt;&quot;+&quot;&lt;/span&gt; : &lt;span class=&quot;string&quot;&gt;&quot;-&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//DisplayDevice的beginFrame函数，调用FrameBufferSurface的beginFrame函数，返回NO_ERROR&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mDisplays[dpy]-&amp;gt;beginFrame(mustRecompose);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mustRecompose) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mDisplays[dpy]-&amp;gt;lastCompositionHadVisibleLayers = !empty;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这一步检查每个显示的dirty区域是否改变了，如果是就要Recompose。DisplayDevice的beginFrame函数，调用FrameBufferSurface的beginFrame函数，返回NO_ERROR。如果需要重新合成，将DisplayDevice的lastCompositionHadVisibleLayers标志只为true（！empty）。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这一步作用不大，可以忽略。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;go on：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;HWComposer&amp;amp; hwc(getHwComposer());  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (hwc.initCheck() == NO_ERROR) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // build the h/w work list  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (CC_UNLIKELY(mHwWorkListDirty)) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mHwWorkListDirty = false;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            for (size_t dpy=0 ; dpy&amp;lt;mDisplays.size() ; dpy++) &amp;#123;//遍历mDisplays  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                sp&amp;lt;const DisplayDevice&amp;gt; hw(mDisplays[dpy]); &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //以前我们讲过，这个id就是不同display的type，比如0，1，2 &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                const int32_t id = hw-&amp;gt;getHwcDisplayId();  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                if (id &amp;gt;= 0) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    const Vector&amp;lt; sp&amp;lt;Layer&amp;gt; &amp;gt;&amp;amp; currentLayers(//遍历DisplayDevice所有可见layer  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        hw-&amp;gt;getVisibleLayersSortedByZ());  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    const size_t count = currentLayers.size();  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    if (hwc.createWorkList(id, count) == NO_ERROR) &amp;#123;//根据layer数量调用createWorkList创建hwc_layer_list_t列表  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        HWComposer::LayerListIterator cur = hwc.begin(id);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        const HWComposer::LayerListIterator end = hwc.end(id);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        for (size_t i=0 ; cur!=end &amp;amp;&amp;amp; i&amp;lt;count ; ++i, ++cur) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            const sp&amp;lt;Layer&amp;gt;&amp;amp; layer(currentLayers[i]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            //设置HWC每一个帧hwc_layer_1_t的Geometry信息&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            //如transform/orientation/alpha等&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            layer-&amp;gt;setGeometry(hw, *cur);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            if (mDebugDisableHWC || mDebugRegion || mDaltonize || mHasColorMatrix) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                cur-&amp;gt;setSkip(true);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这一步主要工作有：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）遍历mDisplays，在所有显示屏信息中，遍历DisplayDevice所有可见layer；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）根据layer数量调用createWorkList创建hwc_layer_list_t列表；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）设置HWC每一个帧hwc_layer_1_t的Geometry信息，如transform/orientation/alpha等。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们先来看下HWComposer的createWorkList函数实现：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; HWComposer::createWorkList(&lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; id, &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; numLayers) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;(id)&amp;gt;&lt;span class=&quot;number&quot;&gt;31&lt;/span&gt; || !mAllocatedDisplayIDs.hasBit(id)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; BAD_INDEX;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mHwc) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;function&quot;&gt;DisplayData&amp;amp; &lt;span class=&quot;title&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mDisplayData[id])&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// we need space for the HWC_FRAMEBUFFER_TARGET&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//当支持Open GL合成时候，会把numLayer数目+1，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//这个多余的1就是合成目标HWC_FRAMEBUFFER_TARGET&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//之前从dumpsys SurfaceFlinger中能看到最后一个是HWC_FRAMEBUFFER_TARGET&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            numLayers++;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;////当DisplayData中的list为空，我们就要malloc  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (disp.capacity &amp;lt; numLayers || disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt; == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//整个申请内存长度，hwc_display_contents_1_t结构体本身的长度加上后面hwc_layer_1_t个数的长度  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; size = &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(&lt;span class=&quot;keyword&quot;&gt;hwc_display_contents_1_t&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    + numLayers * &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(&lt;span class=&quot;keyword&quot;&gt;hwc_layer_1_t&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;built_in&quot;&gt;free&lt;/span&gt;(disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt; = (&lt;span class=&quot;keyword&quot;&gt;hwc_display_contents_1_t&lt;/span&gt;*)&lt;span class=&quot;built_in&quot;&gt;malloc&lt;/span&gt;(size);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.capacity = numLayers;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.framebufferTarget = &amp;amp;disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;-&amp;gt;hwLayers[numLayers - &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//DisplayData的framebufferTarget清0 &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;built_in&quot;&gt;memset&lt;/span&gt;(disp.framebufferTarget, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(&lt;span class=&quot;keyword&quot;&gt;hwc_layer_1_t&lt;/span&gt;));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; DisplayConfig&amp;amp; currentConfig =&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    disp.configs[disp.currentConfig];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;hwc_rect_t&lt;/span&gt; r = &amp;#123; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;) currentConfig.width, (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;) currentConfig.height &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.framebufferTarget-&amp;gt;compositionType = HWC_FRAMEBUFFER_TARGET;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.framebufferTarget-&amp;gt;hints = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.framebufferTarget-&amp;gt;flags = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.framebufferTarget-&amp;gt;handle = disp.fbTargetHandle;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.framebufferTarget-&amp;gt;transform = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.framebufferTarget-&amp;gt;blending = HWC_BLENDING_PREMULT;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//framebufferTarget的sourceCrop初始化&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                disp.framebufferTarget-&amp;gt;sourceCropf.left = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                disp.framebufferTarget-&amp;gt;sourceCropf.top = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                disp.framebufferTarget-&amp;gt;sourceCropf.right =&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        currentConfig.width;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                disp.framebufferTarget-&amp;gt;sourceCropf.bottom =&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        currentConfig.height;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                disp.framebufferTarget-&amp;gt;sourceCrop = r;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//framebufferTarget的displayFrame初始化&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.framebufferTarget-&amp;gt;displayFrame = r;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.framebufferTarget-&amp;gt;visibleRegionScreen.numRects = &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.framebufferTarget-&amp;gt;visibleRegionScreen.rects =&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;amp;disp.framebufferTarget-&amp;gt;displayFrame;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.framebufferTarget-&amp;gt;acquireFenceFd = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.framebufferTarget-&amp;gt;releaseFenceFd = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.framebufferTarget-&amp;gt;planeAlpha = &lt;span class=&quot;number&quot;&gt;0xFF&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;-&amp;gt;retireFenceFd = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;-&amp;gt;flags = HWC_GEOMETRY_CHANGED;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;-&amp;gt;numHwLayers = numLayers;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当支持Open GL合成时候，会把numLayer数目+1，这个多余的1就是合成目标HWC_FRAMEBUFFER_TARGET，之前从dumpsys SurfaceFlinger中能看到最后一个是HWC_FRAMEBUFFER_TARGET。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后就是为DisplayData的list申请内存，这个内存要先hwc_display_contents_1_t结构体本身的长度加上后面hwc_layer_1_t个数的长度。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;后面用DisplayData中list中hwLayers最后一个作为DisplayData中的framebufferTarget。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;最后就是framebufferTarget的一些初始化操作。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;关于DisplayData结构体，可以回顾&lt;a href=&quot;http://windrunnerlihuan.com/2017/05/25/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%BA%94-VSync-%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/&quot;&gt;Android SurfaceFlinger 学习之路(五)—-VSync 工作原理&lt;/a&gt;中的&lt;code&gt;硬件加载&lt;/code&gt;的部分，初始化&lt;strong&gt;显示设备&lt;/strong&gt;和&lt;strong&gt;HWComposer设备&lt;/strong&gt;的内容，这里先贴出来结构体内容：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; DisplayData &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    DisplayData();  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ~DisplayData();  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Vector&amp;lt;DisplayConfig&amp;gt; configs;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; currentConfig;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; format;    &lt;span class=&quot;comment&quot;&gt;// pixel format from FB hal, for pre-hwc-1.1  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; connected;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; hasFbComp;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; hasOvComp;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; capacity;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//上面构造Worklist，并且给DisplayData:list 申请空间&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    hwc_display_contents_1* &lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//DisplayData中list中hwLayers最后一个作为DisplayData中的framebufferTarget&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    hwc_layer_1* framebufferTarget;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt; fbTargetHandle;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;Fence&amp;gt; lastRetireFence;  &lt;span class=&quot;comment&quot;&gt;// signals when the last set op retires  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;Fence&amp;gt; lastDisplayFence; &lt;span class=&quot;comment&quot;&gt;// signals when the last set op takes  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                &lt;span class=&quot;comment&quot;&gt;// effect on screen  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt; outbufHandle;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;Fence&amp;gt; outbufAcquireFence;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// protected by mEventControlLock  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; events;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;DisplayData 结构体的成员list是一个hwc_display_contents_1指针，这个hwc_display_contents_1结构体我们上面讲过。里面有个联合体union，联合体里面又有两个结构体。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;第一个结构体是HWC_DEVICE_VERSION_1_0 使用，dpy和sur对应于EGLDisplay 和 EGLSurface，这是EGL使用的&lt;/li&gt;
&lt;li&gt;第二个结构体是HWC_DEVICE_VERSION_1_3 之后支持 hwcomposer合成多屏，这里是指虚拟屏的输出buffer和对应的fence&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;hwc_display_contents_1后面成员保存了后面还保存了layer的个数和hwc_layer_1_t 数组的起始地址hwLayers[0]。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;DisplayData 结构体的成员framebufferTarget是一个hwc_layer_1指针，这个hwc_layer_1我们上面也贴出来了。相关成员可以参考上面的内容，包括上面提到的 SourceCrop、DisplayFrame和VisibleRegion。其主要数据在buffer_handle_t handle中，buffer_handle_t 其实就是native_handle_t之前分析过，里面有共享内存的fd和地址。关于buffer_handle_t可以回顾之前申请GraphicBuffer的内容。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后就是设置HWC每一个帧hwc_layer_1_t的Geometry信息，如transform/orientation/alpha等。不过这之前我们要先看看HWComposer的begin和end函数，还有相关类或者结构体。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;先看下HWComposer中的begin函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;HWComposer::LayerListIterator HWComposer::begin(&lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; id) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; getLayerIterator(id, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;HWComposer::LayerListIterator HWComposer::getLayerIterator(&lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; id, &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; index) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;(id)&amp;gt;&lt;span class=&quot;number&quot;&gt;31&lt;/span&gt; || !mAllocatedDisplayIDs.hasBit(id)) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//pass&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; LayerListIterator();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; DisplayData&amp;amp; &lt;span class=&quot;title&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mDisplayData[id])&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mHwc || !disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt; || index &amp;gt; disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;-&amp;gt;numHwLayers) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//pass&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; LayerListIterator();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//go to&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; LayerListIterator(&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; HWCLayerVersion1(mHwc, disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;-&amp;gt;hwLayers), index);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里不走前两个if，最后新建一个LayerListIterator对象，构造函数中传入HWCLayerVersion1对象，和index，为0。我们贴出来LayerListIterator类结构：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * Iterator through a HWCLayer list.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * This behaves more or less like a forward iterator.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; LayerListIterator &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;friend&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; HWComposer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    HWCLayer* &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; mLayerList;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; mIndex;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    LayerListIterator() : mLayerList(&lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;), mIndex(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    LayerListIterator(HWCLayer* layer, &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; index)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        : mLayerList(layer), mIndex(index) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// we don&#39;t allow assignment, because we don&#39;t need it for now&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    LayerListIterator&amp;amp; &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt; = (&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; LayerListIterator&amp;amp; rhs);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// copy operators&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    LayerListIterator(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; LayerListIterator&amp;amp; rhs)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        : mLayerList(HWCLayer::copy(rhs.mLayerList)), mIndex(rhs.mIndex) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ~LayerListIterator() &amp;#123; &lt;span class=&quot;keyword&quot;&gt;delete&lt;/span&gt; mLayerList; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// pre-increment&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    LayerListIterator&amp;amp; &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt;++() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mLayerList-&amp;gt;setLayer(++mIndex);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; *&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// dereference&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    HWCLayerInterface&amp;amp; &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt; * () &amp;#123; &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; *mLayerList; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    HWCLayerInterface* &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt; -&amp;gt; () &amp;#123; &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mLayerList; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// comparison&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt; == (&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; LayerListIterator&amp;amp; rhs) &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mIndex == rhs.mIndex;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt; != (&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; LayerListIterator&amp;amp; rhs) &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; !&lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt;==(rhs);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;这里要留意一下后面几个运算符重载，后面会用到。&lt;/strong&gt;&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里面HWCLayerVersion1就是mLayerList， index就是mIndex。HWCLayerVersion1的结构如下：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * Concrete implementation of HWCLayer for HWC_DEVICE_API_VERSION_1_0.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * This implements the HWCLayer side of HWCIterableLayer.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; HWCLayerVersion1 : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; Iterable&amp;lt;HWCLayerVersion1, &lt;span class=&quot;keyword&quot;&gt;hwc_layer_1_t&lt;/span&gt;&amp;gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; hwc_composer_device_1* mHwc;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    HWCLayerVersion1(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; hwc_composer_device_1* hwc, &lt;span class=&quot;keyword&quot;&gt;hwc_layer_1_t&lt;/span&gt;* layer)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        : Iterable&amp;lt;HWCLayerVersion1, &lt;span class=&quot;keyword&quot;&gt;hwc_layer_1_t&lt;/span&gt;&amp;gt;(layer), mHwc(hwc) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//ignore&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;构造函数中传入了mHwc和disp.list-&amp;gt;hwLayers，就是HWC Device HAL层指针和上面我们分析的合成该显示屏的所有Layer。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;而我们再来看看下HWComposer中的end函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;HWComposer::LayerListIterator HWComposer::end(&lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; id) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; numLayers = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;(id) &amp;lt;= &lt;span class=&quot;number&quot;&gt;31&lt;/span&gt; &amp;amp;&amp;amp; mAllocatedDisplayIDs.hasBit(id)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; DisplayData&amp;amp; &lt;span class=&quot;title&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mDisplayData[id])&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mHwc &amp;amp;&amp;amp; disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            numLayers = disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;-&amp;gt;numHwLayers;&lt;span class=&quot;comment&quot;&gt;//获取到list中laye的个数  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// with HWC 1.1, the last layer is always the HWC_FRAMEBUFFER_TARGET,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// which we ignore when iterating through the layer list.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ALOGE_IF(!numLayers, &lt;span class=&quot;string&quot;&gt;&quot;mDisplayData[%d].list-&amp;gt;numHwLayers is 0&quot;&lt;/span&gt;, id);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (numLayers) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    numLayers--;&lt;span class=&quot;comment&quot;&gt;//变成最后一个用于合成的layer，因为本来最后一个是HWC_FRAMEBUFFER_TARGET&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; getLayerIterator(id, numLayers);&lt;span class=&quot;comment&quot;&gt;//和上面一样，只是传入的index不一样。&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;end函数和begin很像只是在调用getLayerIterator的时候，begin传入0，end传入layer的最后一位，变成最后一个用于合成的layer，因为本来最后一个是HWC_FRAMEBUFFER_TARGET。最后就是mIndex成员变量不一样。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接着我们回到上面setUpHWComposer函数，第二部第三个步骤，layer-&amp;gt;setGeometry(hw, （星号，解引用，MD语法转义了这个符号）cur);这里layer是Layer对象，hw是DisplayDevice对象，cur是HWComposer::LayerListIterator对象。&lt;strong&gt;我们上面强调了一定要注意LayerListIterator类内部的运算符重载，这里用到了（星号，解引用，MD语法转义了这个符号）运算符&lt;/strong&gt;：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;HWCLayerInterface&amp;amp; &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt; * () &amp;#123; &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; *mLayerList; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;而上面的mLayerList就是HWCLayerVersion1对象。所以我们继续查看Layer的setGeometry函数：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;void Layer::setGeometry(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const sp&amp;lt;const DisplayDevice&amp;gt;&amp;amp; hw,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        HWComposer::HWCLayerInterface&amp;amp; layer)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    layer.setDefaultState();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // enable this layer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    layer.setSkip(false);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //受安全保护的layer，不可以在进程间传入，所以合成时候跳过&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (isSecure() &amp;amp;&amp;amp; !hw-&amp;gt;isSecure()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        layer.setSkip(true);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // this gives us only the &quot;orientation&quot; component of the transform&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const State&amp;amp; s(getDrawingState());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //半透明颜色处理&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (!isOpaque(s) || s.alpha != 0xFF) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        layer.setBlending(mPremultipliedAlpha ?&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                HWC_BLENDING_PREMULT :&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                HWC_BLENDING_COVERAGE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // apply the layer&#39;s transform, followed by the display&#39;s global transform&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // here we&#39;re guaranteed that the layer&#39;s transform preserves rects&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //处理displayFrame，sourceCrop，还有透明度&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Rect frame(s.transform.transform(computeBounds()));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    frame.intersect(hw-&amp;gt;getViewport(), &amp;amp;frame);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const Transform&amp;amp; tr(hw-&amp;gt;getTransform());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    layer.setFrame(tr.transform(frame));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    layer.setCrop(computeCrop(hw));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    layer.setPlaneAlpha(s.alpha);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    /*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * Transformations are applied in this order:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * 1) buffer orientation/flip/mirror&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * 2) state transformation (window manager)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * 3) layer orientation (screen orientation)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * (NOTE: the matrices are multiplied in reverse order)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const Transform bufferOrientation(mCurrentTransform);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Transform transform(tr * s.transform * bufferOrientation);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //如果这个图形缓冲区之前曾经被旋转过，例如，被水平翻转或者垂直翻转过，那么在对它进行合并之前，还需要将它的旋转方向恢复回来。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (mSurfaceFlingerConsumer-&amp;gt;getTransformToDisplayInverse()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        /*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;         * the code below applies the display&#39;s inverse transform to the buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;         */&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        uint32_t invTransform = hw-&amp;gt;getOrientationTransform();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        uint32_t t_orientation = transform.getOrientation();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // calculate the inverse transform&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (invTransform &amp;amp; NATIVE_WINDOW_TRANSFORM_ROT_90) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    NATIVE_WINDOW_TRANSFORM_FLIP_H;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // If the transform has been rotated the axis of flip has been swapped&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // so we need to swap which flip operations we are performing&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            bool is_h_flipped = (t_orientation &amp;amp; NATIVE_WINDOW_TRANSFORM_FLIP_H) != 0;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            bool is_v_flipped = (t_orientation &amp;amp; NATIVE_WINDOW_TRANSFORM_FLIP_V) != 0;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (is_h_flipped != is_v_flipped) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                t_orientation ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        NATIVE_WINDOW_TRANSFORM_FLIP_H;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // and apply to the current transform&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        transform = Transform(t_orientation) * Transform(invTransform);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // this gives us only the &quot;orientation&quot; component of the transform&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const uint32_t orientation = transform.getOrientation();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (orientation &amp;amp; Transform::ROT_INVALID) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // we can only handle simple transformation&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        layer.setSkip(true);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; else &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        layer.setTransform(orientation);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面就是设置Layer的Geometry信息：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）受安全保护的layer，不可以在进程间传入，所以合成时候跳过。界面受到安全保护的应用程序窗口的内容是不可以在进程间传输的，这个属性主要是应用在屏幕截图中。例如，如果系统中存在一个界面受到安全保护的应用程序窗口，那么我们就不可以请求SurfaceFlinger服务执行截屏功能，因为SurfaceFlinger服务截取下来的屏幕会被传输给请求的进程使用。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）处理displayFrame，sourceCrop，还有透明度。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）如果这个图形缓冲区之前曾经被旋转过，例如，被水平翻转或者垂直翻转过，那么在对它进行合并之前，还需要将它的旋转方向恢复回来。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这样我们setUpHWComposer第二部就完了，go on：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// set the per-frame data&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; dpy=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; dpy&amp;lt;mDisplays.size() ; dpy++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; DisplayDevice&amp;gt; hw(mDisplays[dpy]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; id = hw-&amp;gt;getHwcDisplayId();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (id &amp;gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Vector&amp;lt; sp&amp;lt;Layer&amp;gt; &amp;gt;&amp;amp; currentLayers(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hw-&amp;gt;getVisibleLayersSortedByZ());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; count = currentLayers.size();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        HWComposer::LayerListIterator cur = hwc.begin(id);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; HWComposer::LayerListIterator end = hwc.end(id);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; cur!=end &amp;amp;&amp;amp; i&amp;lt;count ; ++i, ++cur) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             * update the per-frame h/w composer data for each layer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             * and build the transparent region of the FB&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             &lt;span class=&quot;comment&quot;&gt;//将layer的mActiveBuffer设置到HWComposer中去  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;Layer&amp;gt;&amp;amp; layer(currentLayers[i]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            layer-&amp;gt;setPerFrameData(hw, *cur);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;有了上面的基础，我们先留意上面强调过，&lt;strong&gt;注意LayerListIterator类内部的运算符重载&lt;/strong&gt;，这里需要用到的是++的重载：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;LayerListIterator&amp;amp; &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt;++() &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mLayerList-&amp;gt;setLayer(++mIndex);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; *&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; status_t &lt;span class=&quot;title&quot;&gt;setLayer&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; index)&lt;/span&gt; &lt;/span&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentLayer = &amp;amp;mLayerList[index];  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_ERROR;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;会调用mLayerList-&amp;gt;setLayer函数,setLayer会从mLayerList中设置当前的mCurrentLayer，通过mLayerList, 这个变量就是disp.list-&amp;gt;hwLayers。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这样准备工作就好了，我们再来分析Layer的setPerFrameData函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; Layer::setPerFrameData(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; DisplayDevice&amp;gt;&amp;amp; hw,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        HWComposer::HWCLayerInterface&amp;amp; layer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// we have to set the visible region on every frame because&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// we currently free it during onLayerDisplayed(), which is called&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// after HWComposer::commit() -- every frame.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Apply this display&#39;s projection&#39;s viewport to the visible region&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// before giving it to the HWC HAL.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Transform&amp;amp; tr = hw-&amp;gt;getTransform();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Region visible = tr.transform(visibleRegion.intersect(hw-&amp;gt;getViewport()));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    layer.setVisibleRegionScreen(visible);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mSidebandStream.get()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        layer.setSidebandStream(mSidebandStream);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;NOTE:&lt;/span&gt; buffer can be NULL if the client never drew into this&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// layer yet, or if we ran out of memory&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        layer.setBuffer(mActiveBuffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;主要就是调用了HWCLayerVersion1的setBuffer函数:&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;setBuffer&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;GraphicBuffer&amp;gt;&amp;amp; buffer)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (buffer == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; || buffer-&amp;gt;handle == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           getLayer()-&amp;gt;compositionType = HWC_FRAMEBUFFER;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           getLayer()-&amp;gt;flags |= HWC_SKIP_LAYER;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           getLayer()-&amp;gt;handle = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (getLayer()-&amp;gt;compositionType == HWC_SIDEBAND) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;               &lt;span class=&quot;comment&quot;&gt;// If this was a sideband layer but the stream was removed, reset&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;               &lt;span class=&quot;comment&quot;&gt;// it to FRAMEBUFFER. The HWC can change it to OVERLAY in prepare.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;               getLayer()-&amp;gt;compositionType = HWC_FRAMEBUFFER;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;           getLayer()-&amp;gt;handle = buffer-&amp;gt;handle;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   &lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;inline&lt;/span&gt; HWCTYPE* &lt;span class=&quot;title&quot;&gt;getLayer&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;&amp;#123; &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mCurrentLayer; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;用getLayer函数设置其handle，而getLayer就是mCurrentLayer。之前mCurrentLayer会一个个遍历各个Layer,这样就把所有的layer都设置其handle，就是hwc_layer_1_t中的handle。这样就把GraphicBuffer和hwc_layer_1_t关联起来了。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;go on：ignore // If possible, attempt to use the cursor overlay on each display.&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;go on：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;comment&quot;&gt;//将使用哪种合成报告给HWC&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = hwc.prepare();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE_IF(err, &lt;span class=&quot;string&quot;&gt;&quot;HWComposer::prepare failed (%s)&quot;&lt;/span&gt;, strerror(-err));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; dpy=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; dpy&amp;lt;mDisplays.size() ; dpy++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sp&amp;lt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; DisplayDevice&amp;gt; hw(mDisplays[dpy]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//return NO_ERROR&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hw-&amp;gt;prepareFrame(hwc);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;最后会调用HWComposer的prepare函数，将使用哪种合成报告给HWC，我们再来看下这个函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; HWComposer::prepare() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; i&amp;lt;mNumDisplays ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;function&quot;&gt;DisplayData&amp;amp; &lt;span class=&quot;title&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mDisplayData[i])&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (disp.framebufferTarget) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//这里其实就是disp.list中最后一个layer &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// make sure to reset the type to HWC_FRAMEBUFFER_TARGET&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// DO NOT reset the handle field to NULL, because it&#39;s possible&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// that we have nothing to redraw (eg: eglSwapBuffers() not called)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// in which case, we should continue to use the same buffer.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            LOG_FATAL_IF(disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt; == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.framebufferTarget-&amp;gt;compositionType = HWC_FRAMEBUFFER_TARGET;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!disp.connected &amp;amp;&amp;amp; disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt; != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ALOGW(&lt;span class=&quot;string&quot;&gt;&quot;WARNING: disp %zu: connected, non-null list, layers=%zu&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                  i, disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;-&amp;gt;numHwLayers);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mLists[i] = disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;;&lt;span class=&quot;comment&quot;&gt;//DisplayData的list就是mList的一个组员,hwc_display_contents_1* &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mLists[i]) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//HWC_DEVICE_VERSION_1_3 之后支持 hwcomposer合成多屏，这里是指虚拟屏的输出buffer和对应的fence&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mLists[i]-&amp;gt;outbuf = disp.outbufHandle;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mLists[i]-&amp;gt;outbufAcquireFenceFd = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) &amp;#123;&lt;span class=&quot;comment&quot;&gt;// HWC_DEVICE_VERSION_1_0 使用，dpy和sur对应于EGLDisplay 和 EGLSurface&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// garbage data to catch improper use&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mLists[i]-&amp;gt;dpy = (&lt;span class=&quot;keyword&quot;&gt;hwc_display_t&lt;/span&gt;)&lt;span class=&quot;number&quot;&gt;0xDEADBEEF&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mLists[i]-&amp;gt;sur = (&lt;span class=&quot;keyword&quot;&gt;hwc_surface_t&lt;/span&gt;)&lt;span class=&quot;number&quot;&gt;0xDEADBEEF&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mLists[i]-&amp;gt;dpy = EGL_NO_DISPLAY;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mLists[i]-&amp;gt;sur = EGL_NO_SURFACE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     &lt;span class=&quot;comment&quot;&gt;/*对所有显示屏中所有Layer作合成准备（此时也可以开始发送合成的命令码下去，启动硬件合成，但不需要等待完成），hwcomposer需要正确汇报每个Layer的composetype，以告知SurfaceFlinger是否需要额外处理。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    version 为 1.0 的驱动，只支持一个显示屏&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    version 为 1.1 的驱动，只支持物理显示屏&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    version 为 1.3 及以上的驱动，支持物理和虚拟显示屏*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; err = mHwc-&amp;gt;prepare(mHwc, mNumDisplays, mLists);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGE_IF(err, &lt;span class=&quot;string&quot;&gt;&quot;HWComposer: prepare failed (%s)&quot;&lt;/span&gt;, strerror(-err));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// here we&#39;re just making sure that &quot;skip&quot; layers are set&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// to HWC_FRAMEBUFFER and we&#39;re also counting how many layers&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// we have of each type.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// If there are no window layers, we treat the display has having FB&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// composition, because SurfaceFlinger will use GLES to draw the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// wormhole region.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; i&amp;lt;mNumDisplays ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;function&quot;&gt;DisplayData&amp;amp; &lt;span class=&quot;title&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mDisplayData[i])&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.hasFbComp = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disp.hasOvComp = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//下面就是根据hwc汇报的composetype来设置相关属性&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; i&amp;lt;disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;-&amp;gt;numHwLayers ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;hwc_layer_1_t&lt;/span&gt;&amp;amp; l = disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;-&amp;gt;hwLayers[i];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//ALOGD(&quot;prepare: %d, type=%d, handle=%p&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//        i, l.compositionType, l.handle);&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (l.flags &amp;amp; HWC_SKIP_LAYER) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        l.compositionType = HWC_FRAMEBUFFER;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (l.compositionType == HWC_FRAMEBUFFER) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        disp.hasFbComp = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (l.compositionType == HWC_OVERLAY) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        disp.hasOvComp = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (l.compositionType == HWC_CURSOR_OVERLAY) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        disp.hasOvComp = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (disp.&lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;-&amp;gt;numHwLayers == (disp.framebufferTarget ? &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt; : &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    disp.hasFbComp = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                disp.hasFbComp = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt;)err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）遍历每一个显示屏，先取出framebufferTarget进行设置；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）填充mList，DisplayData的list就是mList的一个组员,hwc_display_contents_1*，上面createWorkList讲过；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）根据hwc版本初始化dpy和surface，或者outbuf；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）调用hwc_composer_device_1 的set函数，对所有显示屏中所有Layer作合成准备（此时也可以开始发送合成的命令码下去，启动硬件合成，但不需要等待完成），hwcomposer需要正确汇报每个Layer的composetype，以告知SurfaceFlinger是否需要额外处理。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;5）下面就是根据hwc汇报的composetype来设置相关属性，关于不同type再次贴一遍：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    * HWC_FRAMEBUFFER_TARGET：该Layer是3D合成的目标Layer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    * HWC_FRAMEBUFFER：hwcomposer无法处理此Layer，该Layer需要走3D合成流程，用OpenGL绘制&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    * HWC_OVERLAY：该Layer为硬件合成器所处理，不需要OpenGLES去渲染&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    * HWC_SIDEBAND：该Layer为视频的边频带，需要硬件合成器作特殊处理，若不支持，OpenGL方式只能以一个色块替代，这个标志是外界（应用/驱动）调用窗口系统的perform方法配置的&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    * HWC_CURSOR_OVERLAY：该Layer可通过setCursorPositionAsync 方法改变坐标&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这就是最后一步，提交hwc，然后获得合成类型的步骤。&lt;/p&gt;
&lt;h1 id=&quot;小结&quot;&gt;&lt;a href=&quot;#小结&quot; class=&quot;headerlink&quot; title=&quot;小结&quot;&gt;&lt;/a&gt;小结&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这就是本节内容，太晚了，不想写总结了，先睡了~&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%E4%B8%80%29----%E5%90%88%E6%88%90Layer%E4%B9%8B%E5%87%86%E5%A4%87%E5%90%88%E6%88%90/meizi.jpg&quot; alt=&quot;meizi&quot;&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上一篇我们主要分析了计算Layer的脏区域流程，其中涉及了Buffer状态迁移的后两个步骤：ACQUIRED、RELEADED。本届开始就是正式的合成步骤——REFRESH。但是这个步骤比较复杂，所以先分析合成前的准备工作：重建Layer栈与初始化硬件合成器。&lt;br&gt;
    
    </summary>
    
      <category term="Android技术点" scheme="http://windrunnerlihuan.com/categories/Android%E6%8A%80%E6%9C%AF%E7%82%B9/"/>
    
    
      <category term="SurfaceFlinger" scheme="http://windrunnerlihuan.com/tags/SurfaceFlinger/"/>
    
  </entry>
  
  <entry>
    <title>Android SurfaceFlinger 学习之路(十)----SurfaceFlinger处理Layer更新</title>
    <link href="http://windrunnerlihuan.com/2017/11/09/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%8D%81-SurfaceFlinger%E5%A4%84%E7%90%86Layer%E6%9B%B4%E6%96%B0/"/>
    <id>http://windrunnerlihuan.com/2017/11/09/Android-SurfaceFlinger-学习之路-十-SurfaceFlinger处理Layer更新/</id>
    <published>2017-11-09T09:11:11.000Z</published>
    <updated>2019-01-06T07:30:02.814Z</updated>
    
    <content type="html">&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上次我们分析了SurfaceFlinger的事务处理，对合成前接受上层改变SF和Layer的状态的事务做了统一处理，这节就沿着上次的末尾，继续分析Layer的更新流程。（又断了很久了，实在惭愧，很多事情总是身不由己～）&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;更新Layer-Buffer&quot;&gt;&lt;a href=&quot;#更新Layer-Buffer&quot; class=&quot;headerlink&quot; title=&quot;更新Layer Buffer&quot;&gt;&lt;/a&gt;更新Layer Buffer&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;前几节分析Vsync信号还没有分析完，这一节顺着处理事务的尾巴，处理Layer中Buffer的更新。顺着代码走的，就到了SurfaceFlinger的&lt;code&gt;handlePageFlip&lt;/code&gt;函数。&lt;/p&gt;
&lt;h2 id=&quot;handlePageFlip函数&quot;&gt;&lt;a href=&quot;#handlePageFlip函数&quot; class=&quot;headerlink&quot; title=&quot;handlePageFlip函数&quot;&gt;&lt;/a&gt;handlePageFlip函数&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;page flip是翻页的意思，就是说翻过所有的页面，检查每个Layer的更新。依然位于frameworks/native/serivice/surfaceflinger/SurfaceFlinger.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;void SurfaceFlinger::handlePageFlip()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Region dirtyRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    bool visibleRegions = false;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const LayerVector&amp;amp; layers(mDrawingState.layersSortedByZ);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // Store the set of layers that need updates. This set must not change as&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // buffers are being latched, as this could result in a deadlock.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // Example: Two producers share the same command stream and:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // 1.) Layer 0 is latched&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // 2.) Layer 0 gets a new frame&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // 2.) Layer 1 gets a new frame&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // 3.) Layer 1 is latched.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // Display is now waiting on Layer 1&#39;s frame, which is behind layer 0&#39;s&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // second frame. But layer 0&#39;s second frame could be waiting on display.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Vector&amp;lt;Layer*&amp;gt; layersWithQueuedFrames;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //检查Layer是否需要更新&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    for (size_t i = 0, count = layers.size(); i&amp;lt;count ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const sp&amp;lt;Layer&amp;gt;&amp;amp; layer(layers[i]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //该Layer是否有 QUEUED buffer，上上一篇讲过，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //每当有queued buffer，Layer的onFrameAvailable函数会回调，然后将mQueuedFrames加1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (layer-&amp;gt;hasQueuedFrame())&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //将需要更新的Layer存入这个数组&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            layersWithQueuedFrames.push_back(layer.get());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //遍历每一个需要更新的Layer，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //调用Layer的latchBuffer函数计算Layer的脏区域，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //最后修改Layer所在的Display上的脏区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    for (size_t i = 0, count = layersWithQueuedFrames.size() ; i&amp;lt;count ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Layer* layer = layersWithQueuedFrames[i];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const Region dirty(layer-&amp;gt;latchBuffer(visibleRegions));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const Layer::State&amp;amp; s(layer-&amp;gt;getDrawingState());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        invalidateLayerStack(s.layerStack, dirty);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mVisibleRegionsDirty |= visibleRegions;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;只看这个函数还是挺简单的：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）检查每个Layer，找出需要更新Layer的，并存入数组。我们在&lt;a href=&quot;http://windrunnerlihuan.com/2017/07/03/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%85%AB-Surface%E7%AE%A1%E7%90%86%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BA/&quot;&gt;Android SurfaceFlinger 学习之路(八)—-Surface管理图形缓冲区&lt;/a&gt;中讲过，当把Graphic Buffer 在app侧绘制完后会queue给BufferQueue，此时buffer状态为QUEUED，同时会通知Layer的onFrameAvailable回调去通知SF消费。Layer的onFrameAvailable函数如下，位于rameworks/native/services/surfaceflinger/Layer.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; Layer::onFrameAvailable() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    android_atomic_inc(&amp;amp;mQueuedFrames);&lt;span class=&quot;comment&quot;&gt;//会将mQueuedFrames加1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFlinger-&amp;gt;signalLayerUpdate();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;相应的Layer的hasQueuedFrame函数位于frameworks/native/services/surfaceflinger/Layer.h中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * Returns if a frame is queued.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;hasQueuedFrame&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;/span&gt;&amp;#123; &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mQueuedFrames &amp;gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; || mSidebandStreamChanged; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;因此可以找出需要更新的Layer，然后存入layersWithQueuedFrames这个数组中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）遍历每一个需要更新的Layer，用Layer的latchBuffer函数计算Layer的脏区域。这一步是核心，我们接下来会仔细分析。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）最后修改Layer所在的Display上的脏区域。这一步调用了invalidateLayerStack函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::invalidateLayerStack(&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; layerStack,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Region&amp;amp; dirty) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; dpy=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; dpy&amp;lt;mDisplays.size() ; dpy++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;DisplayDevice&amp;gt;&amp;amp; hw(mDisplays[dpy]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hw-&amp;gt;getLayerStack() == layerStack) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hw-&amp;gt;dirtyRegion.orSelf(dirty);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;先遍历所有的设备，然后找到和Layer的layerstack一样的设备，然后通过“或“运算，将Layer的更新区域加到DisplayDevice的dirtyRegion区域上。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以这个函数的核心就是Layer的latchBuffer函数调用，计算需要更新的苍区域。&lt;/p&gt;
&lt;h2 id=&quot;计算Layer的脏区域&quot;&gt;&lt;a href=&quot;#计算Layer的脏区域&quot; class=&quot;headerlink&quot; title=&quot;计算Layer的脏区域&quot;&gt;&lt;/a&gt;计算Layer的脏区域&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;latchBuffer函数比较长，我们分部查看：&lt;/p&gt;
&lt;h3 id=&quot;Part-1-处理SidebandStream&quot;&gt;&lt;a href=&quot;#Part-1-处理SidebandStream&quot; class=&quot;headerlink&quot; title=&quot;Part.1 处理SidebandStream&quot;&gt;&lt;/a&gt;Part.1 处理SidebandStream&lt;/h3&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;Region Layer::latchBuffer(bool&amp;amp; recomputeVisibleRegions)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //如果sideband surface改变了，表该Layer为视频的边频带，需要硬件合成器作特殊处理，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //然后将 mSidebandStreamChanged置为false&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (android_atomic_acquire_cas(true, false, &amp;amp;mSidebandStreamChanged) == 0) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // mSidebandStreamChanged was true&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSidebandStream = mSurfaceFlingerConsumer-&amp;gt;getSidebandStream();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // sideband的情况，需要重新 计算可视区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        recomputeVisibleRegions = true;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const State&amp;amp; s(getDrawingState());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        return s.transform.transform(Region(Rect(s.active.w, s.active.h)));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Region outDirtyRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //如果Layer中有QUEUED帧&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (mQueuedFrames &amp;gt; 0) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // if we&#39;ve already called updateTexImage() without going through&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // a composition step, we have to skip this layer at this point&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // because we cannot call updateTeximage() without a corresponding&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // compositionComplete() call.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // we&#39;ll trigger an update in onPreComposition().&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (mRefreshPending) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            return outDirtyRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // Capture the old state of the layer for comparisons later&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //注意这里使用的是DrawingState&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const State&amp;amp; s(getDrawingState());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const bool oldOpacity = isOpaque(s);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;GraphicBuffer&amp;gt; oldActiveBuffer = mActiveBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //。。。。。。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这一部分处理了如果是sidebandstream的逻辑，该Layer为视频的边频带，需要硬件合成器作特殊处理，若不支持，OpenGL方式只能以一个色块替代，这个标志是外界（应用/驱动）调用窗口系统的perform方法配置的。&lt;/p&gt;
&lt;h3 id=&quot;Part-2-定义Reject结构体&quot;&gt;&lt;a href=&quot;#Part-2-定义Reject结构体&quot; class=&quot;headerlink&quot; title=&quot;Part.2 定义Reject结构体&quot;&gt;&lt;/a&gt;Part.2 定义Reject结构体&lt;/h3&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;96&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;97&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;98&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;99&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; Reject : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; SurfaceFlingerConsumer::BufferRejecter &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Layer::State&amp;amp; front;&lt;span class=&quot;comment&quot;&gt;//drawingState&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Layer::State&amp;amp; current;&lt;span class=&quot;comment&quot;&gt;//currentState&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt;&amp;amp; recomputeVisibleRegions;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; stickyTransformSet;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Reject(Layer::State&amp;amp; front, Layer::State&amp;amp; current,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt;&amp;amp; recomputeVisibleRegions, &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; stickySet)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                : front(front), current(current),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                  recomputeVisibleRegions(recomputeVisibleRegions),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                  stickyTransformSet(stickySet) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;reject&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;GraphicBuffer&amp;gt;&amp;amp; buf,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; IGraphicBufferConsumer::BufferItem&amp;amp; item)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (buf == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; bufWidth  = buf-&amp;gt;getWidth();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; bufHeight = buf-&amp;gt;getHeight();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// check that we received a buffer of the right size&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// (Take the buffer&#39;s orientation into account)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//旋转90度&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (item.mTransform &amp;amp; Transform::ROT_90) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    swap(bufWidth, bufHeight);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (front.active != front.requested) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//当app请求SF分配图形缓冲区时候，会传入requestWidth和requestHeight&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//如果请求的w和h为0，则isFixedSize为true，此时就要用窗口的大小&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//或者请求的w／h和传入的buffer的w／h相等&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (isFixedSize ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            (bufWidth == front.requested.w &amp;amp;&amp;amp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                             bufHeight == front.requested.h))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// Here we pretend the transaction happened by updating the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// current and drawing states. Drawing state is only accessed&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// in this thread, no need to have it locked&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;//我们假设事务已经提交更新了，current已经赋值给drawing，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;//所以我们不用再去给DrawingState加锁&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;//将request的Geometry区域赋值给active&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        front.active = front.requested;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// We also need to update the current state so that&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// we don&#39;t end-up overwriting the drawing state with&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// this stale current state during the next transaction&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;NOTE:&lt;/span&gt; We don&#39;t need to hold the transaction lock here&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// because State::active is only accessed from this thread.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;//下一次事务提交更新时候，还会讲下一次的current与drawing交换赋值，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;//所以本次我们这里不终止用对这次drawing state对current的覆盖&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        current.active = front.active;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// recompute visible region&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;//重新计算可视区域&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        recomputeVisibleRegions = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//打印些许log&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//如果传入了请求的w／h，并且不是粘性的（往后一直遗留的）转换    &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!isFixedSize &amp;amp;&amp;amp; !stickyTransformSet) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//但是请求的w/h和传入buffer的w/hb不一致&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//那么就需要拒绝掉这个buffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (front.active.w != bufWidth ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        front.active.h != bufHeight) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// reject this buffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;rejecting buffer: bufWidth=%d, bufHeight=%d, front.active.&amp;#123;w=%d, h=%d&amp;#125;&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                bufWidth, bufHeight, front.active.w, front.active.h);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// if the transparent region has changed (this test is&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// conservative, but that&#39;s fine, worst case we&#39;re doing&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// a bit of extra work), we latch the new one and we&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// trigger a visible-region recompute.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//如果透明区域也改变了，也需要更新current的透明区域region，原因同上&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!front.activeTransparentRegion.isTriviallyEqual(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        front.requestedTransparentRegion)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    front.activeTransparentRegion = front.requestedTransparentRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// We also need to update the current state so that&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// we don&#39;t end-up overwriting the drawing state with&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// this stale current state during the next transaction&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;NOTE:&lt;/span&gt; We don&#39;t need to hold the transaction lock here&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// because State::active is only accessed from this thread.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    current.activeTransparentRegion = front.activeTransparentRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// recompute visible region&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//重新计算可视区域&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    recomputeVisibleRegions = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Reject结构体的定义，reject方法判断是否拒绝掉传入的buffer，详细都在注释中写道。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;核心就是如果请求的w／h和传入buffer的w／h不一致，就会拒绝掉这个buffer。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果不拒绝，就更新current和drawing的状态，方便下一次transation处理状态更新，左后将recomputeVisibleRegions置为true，表示重新计算可视区域。&lt;/p&gt;
&lt;h3 id=&quot;Part-3-更新纹理并处理结果&quot;&gt;&lt;a href=&quot;#Part-3-更新纹理并处理结果&quot; class=&quot;headerlink&quot; title=&quot;Part.3 更新纹理并处理结果&quot;&gt;&lt;/a&gt;Part.3 更新纹理并处理结果&lt;/h3&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;//创建一个Reject对象&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                getProducerStickyTransform() != 0);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //更新纹理&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        status_t updateResult = mSurfaceFlingerConsumer-&amp;gt;updateTexImage(&amp;amp;r,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mFlinger-&amp;gt;mPrimaryDispSync);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //延迟显示        &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (updateResult == BufferQueue::PRESENT_LATER) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // Producer doesn&#39;t want buffer to be displayed yet.  Signal a&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // layer update so we check again at the next opportunity.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //延迟显示，触发下一个VSYNC， 即Buffer显示的时间还没到&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mFlinger-&amp;gt;signalLayerUpdate();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            return outDirtyRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // Decrement the queued-frames count.  Signal another event if we&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // have more frames pending.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //减少mQueuedFrames的值 &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //如果还有Queued的Buffer，那么通知 SurfaceFlinger在下一个VSYNC时进行更新&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (android_atomic_dec(&amp;amp;mQueuedFrames) &amp;gt; 1) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mFlinger-&amp;gt;signalLayerUpdate();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //发生了异常&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (updateResult != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // something happened!&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            recomputeVisibleRegions = true;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            return outDirtyRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // update the active buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //mActiveBuffer表示马上要显示的buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //更新mActiveBuffer，得到现在需要输出的图像数据&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mActiveBuffer = mSurfaceFlingerConsumer-&amp;gt;getCurrentBuffer();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (mActiveBuffer == NULL) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ／／异常发生&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // this can only happen if the very first buffer was rejected.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            return outDirtyRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //即将进入 refresh的阶段&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mRefreshPending = true;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mFrameLatencyNeeded = true;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //如果是第一次接收到Buffer, 需要重新计算可视区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (oldActiveBuffer == NULL) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             // the first time we receive a buffer, we need to trigger a&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             // geometry invalidation.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            recomputeVisibleRegions = true;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;         &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Rect crop(mSurfaceFlingerConsumer-&amp;gt;getCurrentCrop());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const uint32_t transform(mSurfaceFlingerConsumer-&amp;gt;getCurrentTransform());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const uint32_t scalingMode(mSurfaceFlingerConsumer-&amp;gt;getCurrentScalingMode());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if ((crop != mCurrentCrop) ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            (transform != mCurrentTransform) ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            (scalingMode != mCurrentScalingMode))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //保存最新的 crop 与transform 这些变量&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mCurrentCrop = crop;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mCurrentTransform = transform;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mCurrentScalingMode = scalingMode;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            recomputeVisibleRegions = true;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //最新的buffer和上一个渲染的buffer的尺寸不一样的，这时需要重新计算可视化区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (oldActiveBuffer != NULL) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            uint32_t bufWidth  = mActiveBuffer-&amp;gt;getWidth();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            uint32_t bufHeight = mActiveBuffer-&amp;gt;getHeight();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (bufWidth != uint32_t(oldActiveBuffer-&amp;gt;width) ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                bufHeight != uint32_t(oldActiveBuffer-&amp;gt;height)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                recomputeVisibleRegions = true;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //透明度相关&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mCurrentOpacity = getOpacityForFormat(mActiveBuffer-&amp;gt;format);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (oldOpacity != isOpaque(s)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            recomputeVisibleRegions = true;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // FIXME: postedRegion should be dirty &amp;amp; bounds&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //计算出脏区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Region dirtyRegion(Rect(s.active.w, s.active.h));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // transform the dirty region to window-manager space&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        outDirtyRegion = (s.transform.transform(dirtyRegion));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    return outDirtyRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;part3最核心的就是更新纹理，之后就是对于返回结果的处理。所以步骤就分两步：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）updateTexImage更新纹理。这一步比较重要，我们接下来单独分析。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）处理更新纹理的结果。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;延迟显示，触发下一个VSYNC， 即Buffer显示的时间还没到；减少mQueuedFrames的值，如果还有Queued的Buffer，那么通知 SurfaceFlinger在下一个VSYNC时进行更新。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果更新纹理发生了异常、第一次接收到buffer、crop和transform区域发生改变、最新的buffer和上一个渲染的buffer的尺寸不一样的、透明度区域发生改变，都需要重新可视化区域。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;最后返回计算出的脏区域。&lt;/p&gt;
&lt;h1 id=&quot;更新纹理&quot;&gt;&lt;a href=&quot;#更新纹理&quot; class=&quot;headerlink&quot; title=&quot;更新纹理&quot;&gt;&lt;/a&gt;更新纹理&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们单独分析更新纹理，SurfaceFlingerConsumer的updateTexImage函数，位于frameworks/native/services/surfaceflinger/SurfaceFlingerConsumer.cpp:&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; DispSync&amp;amp; dispSync)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGV(&lt;span class=&quot;string&quot;&gt;&quot;updateTexImage&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mAbandoned) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//EGL没有初始化&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;updateTexImage: GLConsumer is abandoned!&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_INIT;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Make sure the EGL state is the same as in previous calls.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//检查EGL的状态是否ok&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = checkAndUpdateEglStateLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BufferQueue::BufferItem item;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Acquire the next buffer.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// In asynchronous mode the list is guaranteed to be one buffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// deep, while in synchronous mode we use the oldest buffer.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//获得要显示出来的Buffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//a, 如果上层canvas绘图，获取到的fencefd为-1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//b, 上层opengl绘图，获取到的fencefd不为-1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    err = acquireBufferLocked(&amp;amp;item, computeExpectedPresent(dispSync));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//处理获取buffer异常的状况&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == BufferQueue::NO_BUFFER_AVAILABLE) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            err = NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == BufferQueue::PRESENT_LATER) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// return the error, without logging&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;updateTexImage: acquire failed: %s (%d)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                strerror(-err), err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// We call the rejecter here, in case the caller has a reason to&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// not accept this buffer.  This is used by SurfaceFlinger to&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// reject buffers which have the wrong size&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; buf = item.mBuf;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// 检查是否需要 reject buffer，如果尺寸大小不对，就拒绝掉这个buffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (rejecter &amp;amp;&amp;amp; rejecter-&amp;gt;reject(mSlots[buf].mGraphicBuffer, item)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果拒绝了这个buffer，就要释放它&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, EGL_NO_SYNC_KHR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Release the previous buffer.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// 每次只能处理一个graphic buffer，要将上一次对应的buffer先release了，供别人使用&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//首先创建一个release fence，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//将release fence传递给BufferQueue中的slot对应的mSlots[slot]的mFence&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// 创建GLConsumer里新的EGLImage&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    err = updateAndReleaseLocked(item);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//4.4和以后已经不走这个if了，会在Layer::onDraw中去创建纹理&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!SyncFeatures::getInstance().useNativeFenceSync()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Bind the new buffer to the GL texture.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Older devices require the &quot;implicit&quot; synchronization provided&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// by glEGLImageTargetTexture2DOES, which this method calls.  Newer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// devices will either call this in Layer::onDraw, or (if it&#39;s not&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// a GL-composited layer) not at all.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//绑定EglImage到GL texture&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        err = bindTextureImageLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在这里面会去acquire buffer，然后acquire到的buffer就会去用来合成。主要做的事情：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）acquire一个新的buffer；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）将上一次对应的buffer先release了，并为上次的buffer创建一个release fence，将该release fence传递给BufferQueue中的slot对应的mSlots[slot]的mFence；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）更新mCurrentTexture和mCurrentTextureBuf为这次acquire到的buffer以及slot。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;目前acquire fencefd还没使用，因为还未去合成这个layer，没到用layer中数据的时候。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里有几个重要的步骤，我们分模块分析。&lt;/p&gt;
&lt;h2 id=&quot;获取buffer&quot;&gt;&lt;a href=&quot;#获取buffer&quot; class=&quot;headerlink&quot; title=&quot;获取buffer&quot;&gt;&lt;/a&gt;获取buffer&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;之前我们讲过buffer的状态迁移，又如下一幅图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%29----SurfaceFlinger%E5%A4%84%E7%90%86Layer%E6%9B%B4%E6%96%B0/bufferstatechange.png&quot; alt=&quot;buffer状态迁移&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;之前讲buffer queued进入BufferQueue，然后等等待SF消费。所以SF本次acquire buffer，buffer状态迁移为ACQUIRED。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;顺着上面的步骤，查看acquireBufferLocked函数。不过之前我们先看看参数中computeExpectedPresent函数计算下一次vsync信号到来的时间：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; SurfaceFlingerConsumer::computeExpectedPresent(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; DispSync&amp;amp; dispSync)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// The HWC doesn&#39;t currently have a way to report additional latency.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Assume that whatever we submit now will appear right after the flip.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// For a smart panel this might be 1.  This is expressed in frames,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// rather than time, because we expect to have a constant frame delay&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// regardless of the refresh rate.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; hwcLatency = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Ask DispSync when the next refresh will be (CLOCK_MONOTONIC).&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//调用DispSync的dispSync.computeNextRefresh计算下一次刷新时间&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; nextRefresh = dispSync.computeNextRefresh(hwcLatency);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// The DispSync time is already adjusted for the difference between&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// vsync and reported-vsync (PRESENT_TIME_OFFSET_FROM_VSYNC_NS), so&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// we don&#39;t need to factor that in here.  Pad a little to avoid&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// weird effects if apps might be requesting times right on the edge.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; extraPadding = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (VSYNC_EVENT_PHASE_OFFSET_NS == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        extraPadding = &lt;span class=&quot;number&quot;&gt;1000000&lt;/span&gt;;        &lt;span class=&quot;comment&quot;&gt;// 1ms (6% of 60Hz)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; nextRefresh + extraPadding;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;计算下一次vsync_sf时间，位于frameworks/native/services/surfaceflinger/DispSync.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; DispSync::computeNextRefresh(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; periodOffset) &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; now = systemTime(SYSTEM_TIME_MONOTONIC);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; (((now - mPhase) / mPeriod) + periodOffset + &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;) * mPeriod + mPhase;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;就是一个屏幕刷新周期之后的时间。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;获得了这个实参，然后就查看获取buffer的函数acquireBufferLocked：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; SurfaceFlingerConsumer::acquireBufferLocked(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        BufferQueue::BufferItem *item, &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; presentWhen) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; result = GLConsumer::acquireBufferLocked(item, presentWhen);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (result == NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mTransformToDisplayInverse = item-&amp;gt;mTransformToDisplayInverse;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; result;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里调用了GLConsumer的acquireBufferLocked函数，位于frameworks/native/libs/gui/GLConsumer.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; GLConsumer::acquireBufferLocked(BufferQueue::BufferItem *item,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; presentWhen) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//调用ConsumerBase的acquireBufferLocked函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = ConsumerBase::acquireBufferLocked(item, presentWhen);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// If item-&amp;gt;mGraphicBuffer is not null, this buffer has not been acquired&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// before, so any prior EglImage created is using a stale buffer. This&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// replaces any old EglImage with a new one (using the new buffer).&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果这个buffer已经被acquired，它的图形缓冲区buffer不为空，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//那么一些以前的EglImage就会使用过时的buffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//因此创建GLConsumer里新的EGLImage&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (item-&amp;gt;mGraphicBuffer != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; slot = item-&amp;gt;mBuf;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mEglSlots[slot].mEglImage = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; EglImage(item-&amp;gt;mGraphicBuffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里又调用ConsumerBase的acquireBufferLocked函数去获取buffer。之后，如果这个buffer已经被acquired，它的图形缓冲区buffer不为空，那么一些以前的EglImage就会使用过时的buffer，因此创建GLConsumer里新的EGLImage。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们继续查看ConsumerBase的acquireBufferLocked函数，位于rameworks/native/libs/gui/ConsumerBase.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; ConsumerBase::acquireBufferLocked(BufferQueue::BufferItem *item,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; presentWhen) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//又通过binder IPC调用了BufferQueueConsumer的acquireBuffer函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = mConsumer-&amp;gt;acquireBuffer(item, presentWhen);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//获取到buffer之后，然后赋值给对应mSlots数组中index的BufferSlot&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (item-&amp;gt;mGraphicBuffer != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSlots[item-&amp;gt;mBuf].mGraphicBuffer = item-&amp;gt;mGraphicBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSlots[item-&amp;gt;mBuf].mFrameNumber = item-&amp;gt;mFrameNumber;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSlots[item-&amp;gt;mBuf].mFence = item-&amp;gt;mFence;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    CB_LOGV(&lt;span class=&quot;string&quot;&gt;&quot;acquireBufferLocked: -&amp;gt; slot=%d/%&quot;&lt;/span&gt; PRIu64,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            item-&amp;gt;mBuf, item-&amp;gt;mFrameNumber);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; OK;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里又通过binder IPC调用了BufferQueueConsumer的acquireBuffer函数，位于frameworks/native/libs/gui/BufferQueueConsumer.cpp:&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;96&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;97&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;98&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;99&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;100&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;101&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;102&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;103&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;104&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;105&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;106&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;107&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;108&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;109&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;110&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;111&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;112&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;113&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;114&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;115&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;116&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;117&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;118&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;119&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;120&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;121&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;122&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;123&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;124&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;125&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;126&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;127&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;128&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;129&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;130&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;131&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;132&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;133&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;134&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;135&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;136&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;137&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;138&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;139&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;140&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;141&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;142&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;143&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;144&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;145&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;146&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;147&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;148&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;149&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;150&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;151&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;152&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;153&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;154&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;155&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;156&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;157&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;158&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;159&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;160&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;161&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;162&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;163&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        nsecs_t expectedPresent) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::Autolock lock(mCore-&amp;gt;mMutex);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // Check that the consumer doesn&#39;t currently have the maximum number of&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // buffers acquired. We allow the max buffer count to be exceeded by one&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // buffer so that the consumer can successfully set up the newly acquired&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // buffer before releasing the old one.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //统计mActiveBuffers中已经是 ACQUIRED 的Frame 个数&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    int numAcquiredBuffers = 0;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    for (int s = 0; s &amp;lt; BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //是否已经是 ACQUIRED 的Buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ++numAcquiredBuffers;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //异常检测 &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (numAcquiredBuffers &amp;gt;= mCore-&amp;gt;mMaxAcquiredBufferCount + 1) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        BQ_LOGE(&quot;acquireBuffer: max acquired buffer count reached: %d (max %d)&quot;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                numAcquiredBuffers, mCore-&amp;gt;mMaxAcquiredBufferCount);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        return INVALID_OPERATION;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // Check if the queue is empty.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // In asynchronous mode the list is guaranteed to be one buffer deep,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // while in synchronous mode we use the oldest buffer.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (mCore-&amp;gt;mQueue.empty()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        return NO_BUFFER_AVAILABLE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //queue中的第一个 buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BufferQueueCore::Fifo::iterator front(mCore-&amp;gt;mQueue.begin());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // If expectedPresent is specified, we may not want to return a buffer yet.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // If it&#39;s specified and there&#39;s more than one buffer queued, we may want&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // to drop a buffer.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (expectedPresent != 0) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //一秒作为选择显示的buffer的范围条件&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // The &#39;expectedPresent&#39; argument indicates when the buffer is expected&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // to be presented on-screen. If the buffer&#39;s desired present time is&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // earlier (less) than expectedPresent -- meaning it will be displayed&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // on time or possibly late if we show it as soon as possible -- we&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // acquire and return it. If we don&#39;t want to display it until after the&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // expectedPresent time, we return PRESENT_LATER without acquiring it.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //expectedPresent参数表示的是buffer被我们期望的显示时间。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //如果buffer自己的渴望显示时间早于被期望的时间，意味着它可以按自己渴望时间显示，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //但是也会迟到，比如我们获取了它去迅速返回了，这时候它显示就要迟到了，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //此时我们就要返回一个PRESENT_LATER标志让它在下一次vsync信号去处理。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // To be safe, we don&#39;t defer acquisition if expectedPresent is more&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // than one second in the future beyond the desired present time&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // (i.e., we&#39;d be holding the buffer for a long time).&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //安全起见，我们就不推迟采集被期望的时间大于buffer渴望显示时间超过1秒的buffer了，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //例如，我们长时间持有一个buffer不释放，就会让expectedPresent很大&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // NOTE: Code assumes monotonic time values from the system clock&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // are positive.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // Start by checking to see if we can drop frames. We skip this check if&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // the timestamps are being auto-generated by Surface. If the app isn&#39;t&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // generating timestamps explicitly, it probably doesn&#39;t want frames to&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // be discarded based on them.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // 检查后面的 Queue, 找到最近需要显示的Buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        while (mCore-&amp;gt;mQueue.size() &amp;gt; 1 &amp;amp;&amp;amp; !mCore-&amp;gt;mQueue[0].mIsAutoTimestamp) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // If entry[1] is timely, drop entry[0] (and repeat). We apply an&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // additional criterion here: we only drop the earlier buffer if our&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // desiredPresent falls within +/- 1 second of the expected present.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // Otherwise, bogus desiredPresent times (e.g., 0 or a small&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // relative timestamp), which normally mean &quot;ignore the timestamp&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // and acquire immediately&quot;, would cause us to drop frames.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //如果entry[1]是及时的，就出drop掉entry[0]的buffer，然后继续往后面选。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //我们额外应用一个准则在这里：如果entry[1]的buffer的 desired time落在期望显示时间误差1秒内，那么我们drop掉entry[0]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // We may want to add an additional criterion: don&#39;t drop the&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // earlier buffer if entry[1]&#39;s fence hasn&#39;t signaled yet.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //还有一个准则：如果entry[1]的fence还没有到来，不drop entry[1]的buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const BufferItem&amp;amp; bufferItem(mCore-&amp;gt;mQueue[1]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            nsecs_t desiredPresent = bufferItem.mTimestamp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //如果这个buffer显示的时间在expected之后（garbage），或者将来的1s内会，那么不drop掉上一个. &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // break掉直接显示上一个buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (desiredPresent &amp;lt; expectedPresent - MAX_REASONABLE_NSEC ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    desiredPresent &amp;gt; expectedPresent) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // This buffer is set to display in the near future, or&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // desiredPresent is garbage. Either way we don&#39;t want to drop&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // the previous buffer just to get this on the screen sooner.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                BQ_LOGV(&quot;acquireBuffer: nodrop desire=%&quot; PRId64 &quot; expect=%&quot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        PRId64 &quot; (%&quot; PRId64 &quot;) now=%&quot; PRId64,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        desiredPresent, expectedPresent,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        desiredPresent - expectedPresent,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        systemTime(CLOCK_MONOTONIC));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                break;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            BQ_LOGV(&quot;acquireBuffer: drop desire=%&quot; PRId64 &quot; expect=%&quot; PRId64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &quot; size=%zu&quot;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    desiredPresent, expectedPresent, mCore-&amp;gt;mQueue.size());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //如果上一个需要drop的buffer仍然在slots中，那么标记他为FREE状态        &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (mCore-&amp;gt;stillTracking(front)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // Front buffer is still in mSlots, so mark the slot as free&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mSlots[front-&amp;gt;mSlot].mBufferState = BufferSlot::FREE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //上一个已经没有必要显示了, 重新找一个显示的&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mCore-&amp;gt;mQueue.erase(front);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            front = mCore-&amp;gt;mQueue.begin();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // See if the front buffer is due&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        buffer要显示的时间还没到，那么标记为PRESENT_LATER，下一帧处理&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        nsecs_t desiredPresent = front-&amp;gt;mTimestamp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (desiredPresent &amp;gt; expectedPresent &amp;amp;&amp;amp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                desiredPresent &amp;lt; expectedPresent + MAX_REASONABLE_NSEC) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            BQ_LOGV(&quot;acquireBuffer: defer desire=%&quot; PRId64 &quot; expect=%&quot; PRId64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &quot; (%&quot; PRId64 &quot;) now=%&quot; PRId64,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    desiredPresent, expectedPresent,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    desiredPresent - expectedPresent,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    systemTime(CLOCK_MONOTONIC));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            return PRESENT_LATER;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        BQ_LOGV(&quot;acquireBuffer: accept desire=%&quot; PRId64 &quot; expect=%&quot; PRId64 &quot; &quot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &quot;(%&quot; PRId64 &quot;) now=%&quot; PRId64, desiredPresent, expectedPresent,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                desiredPresent - expectedPresent,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                systemTime(CLOCK_MONOTONIC));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    int slot = front-&amp;gt;mSlot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    *outBuffer = *front;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_BUFFER_INDEX(slot);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BQ_LOGV(&quot;acquireBuffer: acquiring &amp;#123; slot=%d/%&quot; PRIu64 &quot; buffer=%p &amp;#125;&quot;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            slot, front-&amp;gt;mFrameNumber, front-&amp;gt;mGraphicBuffer-&amp;gt;handle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // If the front buffer is still being tracked, update its slot state&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //即将要显示的Buffer没有过期，就要更新状态变为 ACQUIRED&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (mCore-&amp;gt;stillTracking(front)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSlots[slot].mAcquireCalled = true;//BUFFER的状态已经是 ACQUIRED 的了&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSlots[slot].mNeedsCleanupOnRelease = false;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSlots[slot].mBufferState = BufferSlot::ACQUIRED;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSlots[slot].mFence = Fence::NO_FENCE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // If the buffer has previously been acquired by the consumer, set&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // mGraphicBuffer to NULL to avoid unnecessarily remapping this buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // on the consumer side&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //如果buffer之前已经被获取了，设置mGraphicBuffer变量为NULL，避免consumer不必要的二次映射&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (outBuffer-&amp;gt;mAcquireCalled) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        outBuffer-&amp;gt;mGraphicBuffer = NULL;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //将Buffer从 BufferQueueCore列队里移除&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCore-&amp;gt;mQueue.erase(front);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // We might have freed a slot while dropping old buffers, or the producer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // may be blocked waiting for the number of buffers in the queue to&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // decrease.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //我们在第七节讲过，当dequeue buffer时候，slots有可能没有free的buffer可用，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //因此会在producer那儿等待，所以我们这里释放一个slot时候就要去唤醒那儿的lock&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCore-&amp;gt;mDequeueCondition.broadcast();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_INT(mCore-&amp;gt;mConsumerName.string(), mCore-&amp;gt;mQueue.size());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    return NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这也就是我们Buffer迁移状态中ACQUIRED状态的流程，Acquire一个需要处理的Buffer。根据前面对Buffer状态迁移的分析，当消费者想处理一块buffer时，它首先要向BufferQueue做acquire申请。那么BufferQueue怎么知道当前要处理哪一个Buffer呢？这是因为其内部维护有一个Fifo先入先出队列。一旦有buffer被enqueue后，就会压入队尾;每次acquire就从队头取最前面的元素进行处理，完成之后就将其从队列移除。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;代码流程如下：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）统计mActiveBuffers中已经是 ACQUIRED 的Frame 个数，并且检测异常；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）queue中的第一个 buffer，一秒作为选择显示的buffer的范围条件。如果这个entry[1]显示的时间在expected之后（garbage），或者将来的1s内会，那么不drop掉上一个，直接break掉，显示entry[0]；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）如果entry[1]是及时的，就出drop掉entry[0]的buffer，然后继续往后面选；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）buffer要显示的时间还没到，那么标记为PRESENT_LATER，下一帧处理；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;5）更新buffer状态，并从队列中移除。&lt;/p&gt;
&lt;h2 id=&quot;释放buffer并更新状态&quot;&gt;&lt;a href=&quot;#释放buffer并更新状态&quot; class=&quot;headerlink&quot; title=&quot;释放buffer并更新状态&quot;&gt;&lt;/a&gt;释放buffer并更新状态&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Acquire到的buffer封装在BufferItem中，item.mBuf代表它在BufferSlot中的序号。正常情况下item.mGraphicBuffer都不为空，我们将它记录到mEGLSlots[buf].mGraphicBuffer中，以便后续操作。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;消费者一旦处理完Buffer后，就可以将其release了。此后这个buffer就又恢复FREE状态，以供生产者再次dequeue使用。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;那么我们就看看这个释放过程，更新纹理中释放过程，updateAndReleaseLocked函数，实现位于GLConsumer中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; GLConsumer::updateAndReleaseLocked(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; BufferQueue::BufferItem&amp;amp; item)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//招呼slot&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; buf = item.mBuf;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mAttached) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//Open GL ES 是否attach&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ST_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;updateAndRelease: GLConsumer is not attached to an OpenGL &quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;string&quot;&gt;&quot;ES context&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mEglDisplay, EGL_NO_SYNC_KHR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; INVALID_OPERATION;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Confirm state.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//检测EGL状态&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    err = checkAndUpdateEglStateLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mEglDisplay, EGL_NO_SYNC_KHR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Ensure we have a valid EglImageKHR for the slot, creating an EglImage&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// if nessessary, for the gralloc buffer currently in the slot in&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// ConsumerBase.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// We may have to do this even when item.mGraphicBuffer == NULL (which&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// means the buffer was previously acquired).&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//创建 EGLImage ，此时 mEglImage 已经有了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//acquireBufferLocked中找到的即将要显示的 BufferItem 的 GraphicBuffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    err = mEglSlots[buf].mEglImage-&amp;gt;createIfNeeded(mEglDisplay, item.mCrop);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ST_LOGW(&lt;span class=&quot;string&quot;&gt;&quot;updateAndRelease: unable to createImage on display=%p slot=%d&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mEglDisplay, buf);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mEglDisplay, EGL_NO_SYNC_KHR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; UNKNOWN_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Do whatever sync ops we need to do before releasing the old slot.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// 在释放老的buffer前，先给添加一个release fence，有可能还在使用&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    err = syncForReleaseLocked(mEglDisplay);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Release the buffer we just acquired.  It&#39;s not safe to&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// release the old buffer, so instead we just drop the new frame.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// As we are still under lock since acquireBuffer, it is safe to&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// release by slot.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mEglDisplay, EGL_NO_SYNC_KHR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ST_LOGV(&lt;span class=&quot;string&quot;&gt;&quot;updateAndRelease: (slot=%d buf=%p) -&amp;gt; (slot=%d buf=%p)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mCurrentTexture, mCurrentTextureImage != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt; ?&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    mCurrentTextureImage-&amp;gt;graphicBufferHandle() : &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            buf, mSlots[buf].mGraphicBuffer-&amp;gt;handle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// release old buffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// 先把老的buffer，release了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// 如果是第一次为mCurrentTexture为BufferQueue::INVALID_BUFFER_SLOT，-1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// 将release fence传递给BufferQueue中的slot对应的mSlots[slot]的mFence&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//释放buffer  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; status = releaseBufferLocked(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mCurrentTexture, mCurrentTextureImage-&amp;gt;graphicBuffer(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mEglDisplay, mEglSlots[mCurrentTexture].mEglFence);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (status &amp;lt; NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ST_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;updateAndRelease: failed to release buffer: %s (%d)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                   strerror(-status), status);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            err = status;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// keep going, with error raised [?]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Update the GLConsumer state.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// 更新 GLConsumer 状态&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//更新这次acquire到的buffer到mCurrentTexture和mCurrentTextureImage&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentTexture = buf;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentTextureImage = mEglSlots[buf].mEglImage;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentCrop = item.mCrop;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentTransform = item.mTransform;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentScalingMode = item.mScalingMode;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentTimestamp = item.mTimestamp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentFence = item.mFence;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentFrameNumber = item.mFrameNumber;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//对当前的buffer进行矩阵变换处理&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    computeCurrentTransformMatrixLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;updateAndReleaseLocked这个函数释放了buffer，然后更新了mCurrentTexture mCurrentTextureImage等。步骤如下：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）检测Open GL是否连接，EGL状态是否OK；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）创建 EGLImage （此时 mEglImage 已经有了，acquireBufferLocked中找到的即将要显示的 BufferItem 的 GraphicBuffer）；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）释放老的buffer前，先给添加一个release fence，有可能还在使用（&lt;strong&gt;我们本届不讨论Fence相关内容，以后有机会会仔细研究&lt;/strong&gt;）；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）释放buffer（&lt;strong&gt;这个接下来仔细分析&lt;/strong&gt;）；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;5）更新 GLConsumer 状态，更新这次acquire到的buffer到mCurrentTexture和mCurrentTextureImage。 &lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;核心是释放buffer，因此我们看看releaseBufferLocked函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; GLConsumer::releaseBufferLocked(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; buf,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;GraphicBuffer&amp;gt; graphicBuffer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        EGLDisplay display, EGLSyncKHR eglFence) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// release the buffer if it hasn&#39;t already been discarded by the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// BufferQueue. This can happen, for example, when the producer of this&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// buffer has reallocated the original buffer slot after this buffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// was acquired.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = ConsumerBase::releaseBufferLocked(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            buf, graphicBuffer, display, eglFence);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里又调用了ConsumerBase的releaseBufferLocked函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; ConsumerBase::releaseBufferLocked(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; slot, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;GraphicBuffer&amp;gt; graphicBuffer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        EGLDisplay display, EGLSyncKHR eglFence) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// If consumer no longer tracks this graphicBuffer (we received a new&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// buffer on the same slot), the buffer producer is definitely no longer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// tracking it.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!stillTracking(slot, graphicBuffer)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; OK;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    CB_LOGV(&lt;span class=&quot;string&quot;&gt;&quot;releaseBufferLocked: slot=%d/%&quot;&lt;/span&gt; PRIu64,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            slot, mSlots[slot].mFrameNumber);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//release 老buffer的时候，会传入一个mSlots[slot].mFence,即release fence&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ／／调用BufferQueueConsumer的releaseBuffer函数&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = mConsumer-&amp;gt;releaseBuffer(slot, mSlots[slot].mFrameNumber,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            display, eglFence, mSlots[slot].mFence);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果buffer已经过时了但还位于slot中，那么释放他        &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == IGraphicBufferConsumer::STALE_BUFFER_SLOT) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        freeBufferLocked(slot);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSlots[slot].mFence = Fence::NO_FENCE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; ConsumerBase::freeBufferLocked(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; slotIndex) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    CB_LOGV(&lt;span class=&quot;string&quot;&gt;&quot;freeBufferLocked: slotIndex=%d&quot;&lt;/span&gt;, slotIndex);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSlots[slotIndex].mGraphicBuffer = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSlots[slotIndex].mFence = Fence::NO_FENCE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSlots[slotIndex].mFrameNumber = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;继而又调用了BufferQueueConsumer的releaseBuffer函数：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const sp&amp;lt;Fence&amp;gt;&amp;amp; releaseFence, EGLDisplay eglDisplay,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        EGLSyncKHR eglFence) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_BUFFER_INDEX(slot);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (slot &amp;lt; 0 || slot &amp;gt;= BufferQueueDefs::NUM_BUFFER_SLOTS ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            releaseFence == NULL) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        return BAD_VALUE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;IProducerListener&amp;gt; listener;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123; // Autolock scope&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Mutex::Autolock lock(mCore-&amp;gt;mMutex);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // If the frame number has changed because the buffer has been reallocated,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // we can ignore this releaseBuffer for the old buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //如果frameNumber改变了，意味着buffer被重新申请了，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //所以我们要要标记这个老的buffer为STABLE，然后释放掉老的buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (frameNumber != mSlots[slot].mFrameNumber) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            return STALE_BUFFER_SLOT;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // Make sure this buffer hasn&#39;t been queued while acquired by the consumer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //当consumer去acquire buffer时候，确保这个buffer不在BufferQueue当中&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        BufferQueueCore::Fifo::iterator current(mCore-&amp;gt;mQueue.begin());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        while (current != mCore-&amp;gt;mQueue.end()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (current-&amp;gt;mSlot == slot) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                BQ_LOGE(&quot;releaseBuffer: buffer slot %d pending release is &quot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &quot;currently queued&quot;, slot);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                return BAD_VALUE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ++current;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //如果这个buffer被Acquired过了，那么释放他为FREE&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (mSlots[slot].mBufferState == BufferSlot::ACQUIRED) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSlots[slot].mEglDisplay = eglDisplay;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSlots[slot].mEglFence = eglFence;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSlots[slot].mFence = releaseFence;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSlots[slot].mBufferState = BufferSlot::FREE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            listener = mCore-&amp;gt;mConnectedProducerListener;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            BQ_LOGV(&quot;releaseBuffer: releasing slot %d&quot;, slot);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; else if (mSlots[slot].mNeedsCleanupOnRelease) &amp;#123;//如果还存于slot中，是旧的buffer，那么释放他&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            BQ_LOGV(&quot;releaseBuffer: releasing a stale buffer slot %d &quot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &quot;(state = %d)&quot;, slot, mSlots[slot].mBufferState);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSlots[slot].mNeedsCleanupOnRelease = false;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            return STALE_BUFFER_SLOT;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; else &amp;#123;//异常&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            BQ_LOGV(&quot;releaseBuffer: attempted to release buffer slot %d &quot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &quot;but its state was %d&quot;, slot, mSlots[slot].mBufferState);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            return BAD_VALUE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //同上面逻辑，dequeue buffer时候可能会wait，这里唤醒wait锁&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mCore-&amp;gt;mDequeueCondition.broadcast();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; // Autolock scope&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // Call back without lock held&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //回调onBufferReleased函数，调用ConsumerBase::onBuffersReleased&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (listener != NULL) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        listener-&amp;gt;onBufferReleased();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    return NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;释放buffer的逻辑如下：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）异常检测。slot 的index是否合法，是否因为reallocate buffer导致frameNumber改变，当consumer去acquire buffer时候它是否在不在BufferQueue当中；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）释放buffer。如果这个buffer被Acquired过了，那么释放他为FREE；如果还存于slot中，是旧的buffer，那么释放他；异常或者状态异常；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）唤醒dequeue buffer时候的wait lock，回调ConsumerBase::onBuffersReleased，通知buffer释放。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;以上就释放buffer的流程。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;结合上一节内容，经过handleTransaction handlePageFlip两个函数处理，SurfaceFlinger中无论是Layer属性的变化还是图像的变化都处理好了，只等VSync信号到来就可以输出了。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Layer更新中比较重要的就是Buffer状态的迁移，本节主要涉及了Buffer的ACQUIRED和RELEASED状态，这也正好完善了下图的剩下两个流程。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%29----SurfaceFlinger%E5%A4%84%E7%90%86Layer%E6%9B%B4%E6%96%B0/bufferchange2.png&quot; alt=&quot;buffer状态迁移&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;本节内容画一幅时序图如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%29----SurfaceFlinger%E5%A4%84%E7%90%86Layer%E6%9B%B4%E6%96%B0/handlePageFlip.jpg&quot; alt=&quot;handlePageFlip&quot;&gt;&lt;/p&gt;
&lt;h1 id=&quot;小结&quot;&gt;&lt;a href=&quot;#小结&quot; class=&quot;headerlink&quot; title=&quot;小结&quot;&gt;&lt;/a&gt;小结&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;本节主要处理Layer的更新逻辑，先计算layer的脏区域，再更新纹理。更新纹理又包含获取了buffer状态迁移的剩下两环：ACQUIRED、RELEADED。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;至此，处理Vsync信号到来时候的前两环已经处理完结了，即SurfaceFlinger中onMessageReceived回调函数的INVALIDATE CASE。下一节开始就是真正的合成阶段——REFRESH，这是个很复杂的流程，我们仍然会一一分析。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%8D%81%29----SurfaceFlinger%E5%A4%84%E7%90%86Layer%E6%9B%B4%E6%96%B0/daqiao.jpg&quot; alt=&quot;妹子&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;（不如意事常八九，可与语人无二三。）&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上次我们分析了SurfaceFlinger的事务处理，对合成前接受上层改变SF和Layer的状态的事务做了统一处理，这节就沿着上次的末尾，继续分析Layer的更新流程。（又断了很久了，实在惭愧，很多事情总是身不由己～）&lt;br&gt;
    
    </summary>
    
      <category term="Android技术点" scheme="http://windrunnerlihuan.com/categories/Android%E6%8A%80%E6%9C%AF%E7%82%B9/"/>
    
    
      <category term="SurfaceFlinger" scheme="http://windrunnerlihuan.com/tags/SurfaceFlinger/"/>
    
  </entry>
  
  <entry>
    <title>Android SurfaceFlinger 学习之路(九)----SurfaceFlinger事务处理</title>
    <link href="http://windrunnerlihuan.com/2017/10/24/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B9%9D-SurfaceFlinger%E4%BA%8B%E5%8A%A1%E5%A4%84%E7%90%86/"/>
    <id>http://windrunnerlihuan.com/2017/10/24/Android-SurfaceFlinger-学习之路-九-SurfaceFlinger事务处理/</id>
    <published>2017-10-24T08:27:02.000Z</published>
    <updated>2019-01-06T07:28:33.555Z</updated>
    
    <content type="html">&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;荒废三个月，终于更新了~这期间事情巨多，一言难尽~不过对SurfaceFlinger的研究不能停啊，还是要一点一点钻研。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这次继续顺着上次末尾，分析一下SurfaceFlinger事务处理。&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;事务概述&quot;&gt;&lt;a href=&quot;#事务概述&quot; class=&quot;headerlink&quot; title=&quot;事务概述&quot;&gt;&lt;/a&gt;事务概述&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Transaction是“事务”的意思。在我脑海中，关于事务的知识来自于数据库。在数据库操作中，事务意味着一次可以提交多个SQL语句，然后一个commit就可让它们集中执行，而且数据库中的事务还可以回滚，即恢复到事务提交前的状态。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceFlinger为什么需要事务呢？从上面对数据库事务的描述来看，是不是意味着一次执行多个请求呢？我们从数据库事务概念大致可以看出一点端倪, 它的其中一个很重要的信息就是说”&lt;strong&gt;将一组相关操作组合成一个单元去处理&lt;/strong&gt;“。这个思路也运用在了SurfaceFlinger中。我们先举个没有事务的例子，再一个Vsync周期里，Layer的属性改变了很多，比如有大小、位置、透明度、z-order都改变了，并且还不是一个Layer变了，如果每个都改变了，那么如果我们没改变一个属性就去触发相关操作，让SurfaceFlinger去重新合成，这样他岂不是累死了？所以正确的做法是，每当Layer属性改变，先记下来，将所有改变何如一条事务当中，最后在合成前handleTransaction 一次处理掉，这样就省事多了。&lt;/p&gt;
&lt;h2 id=&quot;事务标志&quot;&gt;&lt;a href=&quot;#事务标志&quot; class=&quot;headerlink&quot; title=&quot;事务标志&quot;&gt;&lt;/a&gt;事务标志&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们之前分析java层Surface创建的时候，使用过SurfaceControl这个类，它里面有两个方法，openTransaction和closeTransaction，这就是对Surface操作开事务的方法。不过我们这里先不分析这个，我们先看看C++层这一侧的事务。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;事务的标志有以下几种，位于frameworks/native/services/surfaceflinger/SurfaceFlinger.h中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;enum&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    eTransactionNeeded        = &lt;span class=&quot;number&quot;&gt;0x01&lt;/span&gt;,&lt;span class=&quot;comment&quot;&gt;//Layer的属性发生变化了，表示需要处理事务&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    eTraversalNeeded          = &lt;span class=&quot;number&quot;&gt;0x02&lt;/span&gt;,&lt;span class=&quot;comment&quot;&gt;//遍历的是SurfaceFlinger中所有的Layer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    eDisplayTransactionNeeded = &lt;span class=&quot;number&quot;&gt;0x04&lt;/span&gt;,&lt;span class=&quot;comment&quot;&gt;//这个是显示器相关的事务,如显示器hotplug&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    eTransactionMask          = &lt;span class=&quot;number&quot;&gt;0x07&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//掩码&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;事务标志也可以是多种组合，也很好理解，十六进制位，每种标志占一位，掩码占全位。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;每种的意义在注释写的比较清楚。&lt;/p&gt;
&lt;h2 id=&quot;设置和处理flags&quot;&gt;&lt;a href=&quot;#设置和处理flags&quot; class=&quot;headerlink&quot; title=&quot;设置和处理flags&quot;&gt;&lt;/a&gt;设置和处理flags&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;mTransactionFlags是surface flinger中的一个成员，注意在layer中也存在一个同名的mTransactionFlags，通过下面的函数设置该flag，位于frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; SurfaceFlinger::setTransactionFlags(&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//或返回的是mTransactionFlags旧的值&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; old = android_atomic_or(flags, &amp;amp;mTransactionFlags);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果旧值和flags没有bit是相同的?&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((old &amp;amp; flags)==&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123; &lt;span class=&quot;comment&quot;&gt;// wake the server up,触发一次invalidate&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        signalTransaction();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; old;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在surfaceflinger中，&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;createLayer()，removeLayer()，setClientStateLocked都会去设置事务flag为eTransactionNeeded；&lt;/li&gt;
&lt;li&gt;setClientStateLocked()会去设置eTraversalNeeded；&lt;/li&gt;
&lt;li&gt;createDisplay()，destroyDisplay()，onHotplugReceived()，setDisplayStateLocked()会去设置eDisplayTransactionNeeded。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后就是调用SurfaceFlinger的signalTransaction，我们看看它：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::signalTransaction() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEventQueue.invalidate();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个我们之前分析过，调用MessageQueue的invalidate函数，位于frameworks/native/services/surfaceflinger/MessageQueue.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;define&lt;/span&gt; INVALIDATE_ON_VSYNC 1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; MessageQueue::invalidate() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// INVALIDATE_ON_VSYNC宏默认为true&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; INVALIDATE_ON_VSYNC&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEvents-&amp;gt;requestNextVsync();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;else&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mHandler-&amp;gt;dispatchInvalidate();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;mEvents就是EventThread类中的Connection类，第五篇分析vsync的时候介绍过，位于frameworks/native/services/surfaceflinger/EventThread.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; EventThread::Connection::requestNextVsync() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEventThread-&amp;gt;requestNextVsync(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// 关于Connection中的count，当为0时为一次性的事件，即触发一次sync信号&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// count &amp;gt;= 1 : continuous event. count is the vsync rate&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// count == 0 : one-shot event that has not fired&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// count ==-1 : one-shot event that fired this round / disabled&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; EventThread::requestNextVsync(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;EventThread::Connection&amp;gt;&amp;amp; connection) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::Autolock _l(mLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (connection-&amp;gt;count &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        connection-&amp;gt;count = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mCondition.broadcast();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里将mCondition wait的地方释放，在&lt;a href=&quot;http://windrunnerlihuan.com/2017/05/25/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%BA%94-VSync-%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/&quot;&gt;Android SurfaceFlinger 学习之路(五)—-VSync 工作原理&lt;/a&gt;我们分析过，各种事务都会去触发一次vsync，前面文章分析过，在每次vsync信号到来时，处理这个vsync事件会去调用SurfaceFlinger的onMessageReceived函数，我们看看它的实现:&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::onMessageReceived(&lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; what) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt; (what) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; MessageQueue::TRANSACTION:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        handleMessageTransaction();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//我们走的是这个case&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; MessageQueue::INVALIDATE:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        handleMessageTransaction();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        handleMessageInvalidate();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        signalRefresh();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; MessageQueue::REFRESH:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        handleMessageRefresh();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们走的是第二个case。这里先分析这个case第一个函数调用，后面的部分是SurfaceFlinger合成步骤，我们后续在分析。进而调用handleMessageTransaction，根据mTransactionFlags中设置的bit值做相应的处理。&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::handleMessageTransaction() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; transactionFlags = peekTransactionFlags(eTransactionMask);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (transactionFlags) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        handleTransaction(transactionFlags);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这样就回到我们今天的主题了，对事务的处理，我们接下来会逐步分析。&lt;/p&gt;
&lt;h1 id=&quot;SurfaceFlinger处理事务&quot;&gt;&lt;a href=&quot;#SurfaceFlinger处理事务&quot; class=&quot;headerlink&quot; title=&quot;SurfaceFlinger处理事务&quot;&gt;&lt;/a&gt;SurfaceFlinger处理事务&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们首先要看SurfaceFlinger几个重要的变量：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;State mCurrentState&lt;br&gt;SurfaceFlinger下一帧的状态，即表示即将绘制的下一帧的状态。&lt;/li&gt;
&lt;li&gt;State mDrawingState&lt;br&gt;当前正在绘制的状态，即表示上一帧处理完事务后更新出来的状态，是最终的状态。&lt;/li&gt;
&lt;li&gt;mVisibleRegionsDirty&lt;br&gt;表示当前可见区域是否脏了，如果脏了的话，比如(layer added/removed, Display added/remove相关)在最后合成的时候会对每个屏幕重建layer stack, 但是一般都为false。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这两个状态是SurfaceFlinger中的State，在Layer当中也有一个State，我们后面会讲到，我们看看这个State的定义，位于frameworks/native/services/surfaceflinger/SurfaceFlinger.h：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; State &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    LayerVector layersSortedByZ;&lt;span class=&quot;comment&quot;&gt;//SurfaceFlinger中所有的按照Z order排序的 Layer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    DefaultKeyedVector&amp;lt; wp&amp;lt;IBinder&amp;gt;, DisplayDeviceState&amp;gt; displays;&lt;span class=&quot;comment&quot;&gt;//外接的显示屏&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;前者是上一次“drawing”时的状态，而后者则是当前状态。这样我们只要通过对比这两个State，就知道系统中发生了什么变化，然后采取相应的措施。它们内部都包含了一个LayerVector类型的layersSortedByZ成员变量，从变量名可以看出是所有layers按照Z-order顺序排列的Vector。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以我们可以从mCurrentState.layersSortedByZ来访问到所有layer，然后对有需要执行transaction的图层再调用内部的doTransaction()。显然，并不是每个layer在每次handleTransactionLocked中都需要调用doTransaction，判断的标准就是Layer::getTransactionFlags返回的标志中是否要求了eTransactionNeeded。大家要注意SurfaceFlinger和各Layer都有一个mTransactionFlags变量，不过含义不同。另外，Layer中也同样有mCurrentState和mDrawingState，虽然它们也分别表示上一次和当前的状态，但所属的State结构体是完全不同的。&lt;/p&gt;
&lt;h2 id=&quot;handleTransaction&quot;&gt;&lt;a href=&quot;#handleTransaction&quot; class=&quot;headerlink&quot; title=&quot;handleTransaction&quot;&gt;&lt;/a&gt;handleTransaction&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们顺着上一节末位，处理vsync信号之后要去合成，之前先处理事务。因此走到了SurfaceFlinger的handleTransaction函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::handleTransaction(&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; transactionFlags)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// here we keep a copy of the drawing state (that is the state that&#39;s&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// going to be overwritten by handleTransactionLocked()) outside of&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// mStateLock so that the side-effects of the State assignment&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// don&#39;t happen with mStateLock held (which can cause deadlocks).&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//保存mDrawingState，但是却没有使用，are you kidding me？&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;State &lt;span class=&quot;title&quot;&gt;drawingState&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mDrawingState)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::Autolock _l(mStateLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; now = systemTime();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDebugInTransaction = now;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Here we&#39;re guaranteed that some transaction flags are set&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// so we can call handleTransactionLocked() unconditionally.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// We call getTransactionFlags(), which will also clear the flags,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// with mStateLock held to guarantee that mCurrentState won&#39;t change&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// until the transaction is committed.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;////获得SurfaceFlinger中的Transaction标志位&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    transactionFlags = getTransactionFlags(eTransactionMask);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//在这里处理Transaction&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    handleTransactionLocked(transactionFlags);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mLastTransactionTime = systemTime() - now;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDebugInTransaction = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    invalidateHwcGeometry();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// here the transaction has been committed&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;先获取了SurfaceFlinger的transactionFlags ，然后调用handleTransactionLocked处理这些事务。这个函数很长，我们需要分步查看。&lt;/p&gt;
&lt;h3 id=&quot;Part-1-遍历所有的Layer-让Layer去执行自己的事务&quot;&gt;&lt;a href=&quot;#Part-1-遍历所有的Layer-让Layer去执行自己的事务&quot; class=&quot;headerlink&quot; title=&quot;Part.1 遍历所有的Layer, 让Layer去执行自己的事务&quot;&gt;&lt;/a&gt;Part.1 遍历所有的Layer, 让Layer去执行自己的事务&lt;/h3&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::handleTransactionLocked(&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; transactionFlags)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//获取当前所有Layer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; LayerVector&amp;amp; &lt;span class=&quot;title&quot;&gt;currentLayers&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mCurrentState.layersSortedByZ)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; count = currentLayers.size();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * Traversal of the children&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * (perform the transaction for each of them if needed)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//先判断有没有eTraversalNeeded标志位&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (transactionFlags &amp;amp; eTraversalNeeded) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//然后遍历所有Layer,让Layer去执行自己的事务&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; i&amp;lt;count ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;Layer&amp;gt;&amp;amp; layer(currentLayers[i]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//获取Layer的transaction flags&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; trFlags = layer-&amp;gt;getTransactionFlags(eTransactionNeeded);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!trFlags) &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// Layer处理自己的事务&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags = layer-&amp;gt;doTransaction(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//如果Layer的可见区域改变了，则SurfaceFlinger就标注出当前可视区域改变了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (flags &amp;amp; Layer::eVisibleRegion)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mVisibleRegionsDirty = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;先获取下一帧状态State所有的Layer,然后判断SF有没有eTraversalNeeded标志位，如果有，则遍历所有的Layer，让Layer去执行自己的事务，如果Layer的可见区域改变了，则SurfaceFlinger就标注出当前可视区域改变了，将mVisibleRegionsDirty 置为true。&lt;/p&gt;
&lt;h3 id=&quot;Part-2-处理显示屏相关事务&quot;&gt;&lt;a href=&quot;#Part-2-处理显示屏相关事务&quot; class=&quot;headerlink&quot; title=&quot;Part.2 处理显示屏相关事务&quot;&gt;&lt;/a&gt;Part.2 处理显示屏相关事务&lt;/h3&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;96&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;97&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;98&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;99&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;100&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;101&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;102&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;103&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;104&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;105&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;106&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;107&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;108&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;109&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;110&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;111&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;112&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;113&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;114&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;115&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;116&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;117&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;118&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;119&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;120&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;121&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;122&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;123&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;124&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;125&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;126&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;127&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;128&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;129&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;130&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;131&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;132&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;133&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;134&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;135&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;136&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;137&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;138&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;139&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;140&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;141&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;142&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;143&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;144&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;145&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;146&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;147&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;148&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;149&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;150&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;151&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;152&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;153&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;154&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;155&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;156&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;157&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;158&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;159&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;160&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;161&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;162&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;163&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;164&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;165&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;166&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;167&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;168&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;169&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;170&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;171&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;172&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;173&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;174&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;175&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;176&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;177&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;178&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;179&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;180&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;181&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;182&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;183&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::handleTransactionLocked(&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; transactionFlags)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.1&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * Perform display own transactions if needed&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果有eDisplayTransactionNeeded标志位&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (transactionFlags &amp;amp; eDisplayTransactionNeeded) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// here we take advantage of Vector&#39;s copy-on-write semantics to&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// improve performance by skipping the transaction entirely when&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// know that the lists are identical&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//当我们知道上一次绘制状态和当前需要去绘制状态的显示屏信息相同时，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//通过完全跳过事务，我们利用Vector的copy-on-write的特点去提高性能&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//下一帧State的显示屏信息&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; KeyedVector&amp;lt;  wp&amp;lt;IBinder&amp;gt;, DisplayDeviceState&amp;gt;&amp;amp; curr(mCurrentState.displays);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//上一次绘制状态State的显示屏信息&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; KeyedVector&amp;lt;  wp&amp;lt;IBinder&amp;gt;, DisplayDeviceState&amp;gt;&amp;amp; draw(mDrawingState.displays);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果下一帧State的显示屏信息和上一次绘制状态State的显示屏信息不同&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!curr.isIdenticalTo(draw)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//表示当前可见区域脏了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mVisibleRegionsDirty = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//下一帧需要显示状态&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; cc = curr.size();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                  &lt;span class=&quot;comment&quot;&gt;//上一帧绘制状态&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                  &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; dc = draw.size();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// find the displays that were removed&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// (ie: in drawing state but not in current state)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// also handle displays that changed&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// (ie: displays that are in both lists)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//对比上一帧绘制状态，找到我们移除的显示屏&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; i&amp;lt;dc ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;ssize_t&lt;/span&gt; j = curr.indexOfKey(draw.keyAt(i));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//移除显示屏的index&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (j &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// in drawing state but not in current state&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//移除的不是主显示屏&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!draw[i].isMainDisplay()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// Call makeCurrent() on the primary display so we can&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// be sure that nothing associated with this display&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// is current.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;//主显示屏调用makeCurrent函数确保移除的显示屏和它没有联系了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; DisplayDevice&amp;gt; defaultDisplay(getDefaultDisplayDevice());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        defaultDisplay-&amp;gt;makeCurrent(mEGLDisplay, mEGLContext);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        sp&amp;lt;DisplayDevice&amp;gt; hw(getDisplayDevice(draw.keyAt(i)));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;//断开连接&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hw != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            hw-&amp;gt;disconnect(getHwComposer());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (draw[i].type &amp;lt; DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            &lt;span class=&quot;comment&quot;&gt;//并回调热插拔接口onHotplugReceived，用于触发下一次vsync信号相应事件&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            mEventThread-&amp;gt;onHotplugReceived(draw[i].type, &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        mDisplays.removeItem(draw.keyAt(i));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        ALOGW(&lt;span class=&quot;string&quot;&gt;&quot;trying to remove the main display&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//如果这个显示屏没有被移除，看看它是否改变了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// this display is in both lists. see if something changed.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; DisplayDeviceState&amp;amp; state(curr[j]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; wp&amp;lt;IBinder&amp;gt;&amp;amp; display(curr.keyAt(j));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (state.surface-&amp;gt;asBinder() != draw[i].surface-&amp;gt;asBinder()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// changing the surface is like destroying and&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// recreating the DisplayDevice, so we just remove it&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// from the drawing state, so that it get re-added&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// below.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;//如果显示屏是销毁又重建的，所以没有被移除，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;//那么我们要移除并重新添加他&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        sp&amp;lt;DisplayDevice&amp;gt; hw(getDisplayDevice(display));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hw != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            hw-&amp;gt;disconnect(getHwComposer());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        mDisplays.removeItem(display);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        mDrawingState.displays.removeItemsAt(i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        dc--; i--;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// at this point we must loop to the next item&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;DisplayDevice&amp;gt; disp(getDisplayDevice(display));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//查看显示屏信息是否改变了，如果变了，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//就要重新将drawing信息赋值为current&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (disp != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;//z-order排布的layer层改变了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (state.layerStack != draw[i].layerStack) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            disp-&amp;gt;setLayerStack(state.layerStack);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;//方向、视角、帧结构改变了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((state.orientation != draw[i].orientation)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                || (state.viewport != draw[i].viewport)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                || (state.frame != draw[i].frame))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            disp-&amp;gt;setProjection(state.orientation,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                    state.viewport, state.frame);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;//大小改变了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (state.width != draw[i].width || state.height != draw[i].height) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            disp-&amp;gt;setDisplaySize(state.width, state.height);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// find displays that were added&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// (ie: in current state but not in drawing state)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//找到我们新增加的显示屏信息&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; i&amp;lt;cc ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (draw.indexOfKey(curr.keyAt(i)) &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; DisplayDeviceState&amp;amp; &lt;span class=&quot;title&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(curr[i])&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//新增显示屏，需要一些变量属性：&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//FrameBufferSurface、BufferQueueProducer、&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//BufferQueueConsumer等&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    sp&amp;lt;DisplaySurface&amp;gt; dispSurface;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    sp&amp;lt;IGraphicBufferProducer&amp;gt; producer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    sp&amp;lt;IGraphicBufferProducer&amp;gt; bqProducer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    sp&amp;lt;IGraphicBufferConsumer&amp;gt; bqConsumer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    BufferQueue::createBufferQueue(&amp;amp;bqProducer, &amp;amp;bqConsumer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; GraphicBufferAlloc());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; hwcDisplayId = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//如果是虚拟设备&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (state.isVirtualDisplay()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// Virtual displays without a surface are dormant:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// they have external state (layer stack, projection,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// etc.) but no internal state (i.e. a DisplayDevice).&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (state.surface != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            hwcDisplayId = allocateHwcDisplayId(state.type);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            sp&amp;lt;VirtualDisplaySurface&amp;gt; vds = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; VirtualDisplaySurface(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                    *mHwc, hwcDisplayId, state.surface,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                    bqProducer, bqConsumer, state.displayName);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            dispSurface = vds;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            producer = vds;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;//如果不是虚拟设备&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        ALOGE_IF(state.surface!=&lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                &lt;span class=&quot;string&quot;&gt;&quot;adding a supported display, but rendering &quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                &lt;span class=&quot;string&quot;&gt;&quot;surface is provided (%p), ignoring it&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                state.surface.get());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;//申请设备id&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        hwcDisplayId = allocateHwcDisplayId(state.type);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// for supported (by hwc) displays we provide our&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// own rendering surface&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;//创建FrameBufferSurface用于渲染显示&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        dispSurface = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; FramebufferSurface(*mHwc, state.type,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                bqConsumer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        producer = bqProducer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; wp&amp;lt;IBinder&amp;gt;&amp;amp; display(curr.keyAt(i));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//设置显示屏相关属性&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (dispSurface != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;//创建显示屏信息&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        sp&amp;lt;DisplayDevice&amp;gt; hw = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; DisplayDevice(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                state.type, hwcDisplayId,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                mHwc-&amp;gt;getFormat(hwcDisplayId), state.isSecure,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                display, dispSurface, producer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                mRenderEngine-&amp;gt;getEGLConfig());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        hw-&amp;gt;setLayerStack(state.layerStack);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        hw-&amp;gt;setProjection(state.orientation,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                state.viewport, state.frame);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        hw-&amp;gt;setDisplayName(state.displayName);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        mDisplays.add(display, hw);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (state.isVirtualDisplay()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hwcDisplayId &amp;gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                mHwc-&amp;gt;setVirtualDisplayProperties(hwcDisplayId,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                        hw-&amp;gt;getWidth(), hw-&amp;gt;getHeight(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                        hw-&amp;gt;getFormat());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            mEventThread-&amp;gt;onHotplugReceived(state.type, &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;代码虽然多，但是逻辑很清晰，做的事情主要如下：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）对比上一帧绘制状态，找到我们移除的显示屏。如果找到移除的就要断开连接，并且remove；如果没有移除，则判断是否为destroy-recreate的，如果是，则要移除重新add进来，如果不是，则看看是否状态发生改变，然后设置current状态；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）找到我们新增加的显示屏信息。新增显示屏，则要创建DisplayDevice描述对象，构建这个对象又需要FrameBufferSurface用于渲染显示，构建FrameBufferSurface又需要BufferQueue一套对象，因此一一创建。&lt;/p&gt;
&lt;h3 id=&quot;Part-3-找到Layer所在显示屏并更新旋转方向&quot;&gt;&lt;a href=&quot;#Part-3-找到Layer所在显示屏并更新旋转方向&quot; class=&quot;headerlink&quot; title=&quot;Part.3 找到Layer所在显示屏并更新旋转方向&quot;&gt;&lt;/a&gt;Part.3 找到Layer所在显示屏并更新旋转方向&lt;/h3&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::handleTransactionLocked(&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; transactionFlags)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.1&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.2&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (transactionFlags &amp;amp; (eTraversalNeeded|eDisplayTransactionNeeded)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// The transform hint might have changed for some layers&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// (either because a display has changed, or because a layer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// as changed).&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Walk through all the layers in currentLayers,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// and update their transform hint.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// If a layer is visible only on a single display, then that&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// display is used to calculate the hint, otherwise we use the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// default display.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;NOTE:&lt;/span&gt; we do this here, rather than in rebuildLayerStacks() so that&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// the hint is set before we acquire a buffer from the surface texture.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;NOTE:&lt;/span&gt; layer transactions have taken place already, so we use their&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// drawing state. However, SurfaceFlinger&#39;s own transaction has not&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// happened yet, so we must use the current state layer list&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// (soon to become the drawing state list).&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; DisplayDevice&amp;gt; disp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; currentlayerStack = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i&amp;lt;count; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;NOTE:&lt;/span&gt; we rely on the fact that layers are sorted by&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// layerStack first (so we don&#39;t have to traverse the list&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// of displays for every layer).&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;Layer&amp;gt;&amp;amp; layer(currentLayers[i]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; layerStack = layer-&amp;gt;getDrawingState().layerStack;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//通过遍历所有的Display来找到Layer所在的显示屏&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (i==&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; || currentlayerStack != layerStack) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                currentlayerStack = layerStack;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// figure out if this layerstack is mirrored&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// (more than one display) if so, pick the default display,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// if not, pick the only display it&#39;s on.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                disp.clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; dpy=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; dpy&amp;lt;mDisplays.size() ; dpy++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    sp&amp;lt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; DisplayDevice&amp;gt; hw(mDisplays[dpy]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hw-&amp;gt;getLayerStack() == currentlayerStack) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (disp == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            disp = hw;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            disp = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (disp == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;NOTE:&lt;/span&gt; TEMPORARY FIX ONLY. Real fix should cause layers to&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// redraw after transform hint changes. See bug 8508397.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// could be null when this layer is using a layerStack&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// that is not visible on any display. Also can occur at&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// screen off/on times.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                disp = getDefaultDisplayDevice();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//更新Layer的旋转方向，最终会体现在 BufferQueueCore中的mTransformHint变量&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            layer-&amp;gt;updateTransformHint(disp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Part3做的事情主要是找到Layer所在显示屏并更新旋转方向，也是layer的事务。&lt;/p&gt;
&lt;h3 id=&quot;Part-4-处理Layer移除逻辑&quot;&gt;&lt;a href=&quot;#Part-4-处理Layer移除逻辑&quot; class=&quot;headerlink&quot; title=&quot;Part.4 处理Layer移除逻辑&quot;&gt;&lt;/a&gt;Part.4 处理Layer移除逻辑&lt;/h3&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part.1...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part.2...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part.3...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    /*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * Perform our own transaction if needed&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //如果需要合成的layer小于上一次绘制状态的layer个数，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //则有Layer需要去移除&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const LayerVector&amp;amp; layers(mDrawingState.layersSortedByZ);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (currentLayers.size() &amp;gt; layers.size()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // layers have been added&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mVisibleRegionsDirty = true;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // some layers might have been removed, so&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // we need to update the regions they&#39;re exposing.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //下面有layer移除的情况&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (mLayersRemoved) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mLayersRemoved = false;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mVisibleRegionsDirty = true;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const size_t count = layers.size();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        for (size_t i=0 ; i&amp;lt;count ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const sp&amp;lt;Layer&amp;gt;&amp;amp; layer(layers[i]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //找到移除的layer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (currentLayers.indexOf(layer) &amp;lt; 0) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // this layer is not visible anymore&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // TODO: we could traverse the tree from front to back and&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //       compute the actual visible region&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // TODO: we could cache the transformed region&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                const Layer::State&amp;amp; s(layer-&amp;gt;getDrawingState());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //获得移除的Layer的可见区域, 这块可见区域就是dirty的&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                Region visibleReg = s.transform.transform(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        Region(Rect(s.active.w, s.active.h)));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //找到被移除掉的Layer所在的Display, 然后更新Diplay的dirty 区域，也就是对region做或运算&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                invalidateLayerStack(s.layerStack, visibleReg);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //提交事务&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    commitTransaction();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //更新显示屏中的光标&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    updateCursorAsync();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这一段主要处理Layer的移除逻辑。如果需要合成的layer小于上一次绘制状态的layer个数，则有layer需要去移除。找到需要移除的Layer，获得可见区域，然后更新Display的dirty区域，也就是对region做或运算。&lt;/p&gt;
&lt;h2 id=&quot;提交事务&quot;&gt;&lt;a href=&quot;#提交事务&quot; class=&quot;headerlink&quot; title=&quot;提交事务&quot;&gt;&lt;/a&gt;提交事务&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;剩下就是提交事务和更新显示屏的光标了，我们看看提交事务。&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::commitTransaction()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//mLayersPendingRemoval是保存的是pending 着需要移除的Layer. &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//比如APP调用destroySurface&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mLayersPendingRemoval.isEmpty()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Notify removed layers now that they can&#39;t be drawn from&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; mLayersPendingRemoval.size(); i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mLayersPendingRemoval[i]-&amp;gt;onRemoved();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mLayersPendingRemoval.clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// If this transaction is part of a window animation then the next frame&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// we composite should be considered an animation as well.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mAnimCompositionPending = mAnimTransactionPending;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//更新 mDrawingState&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDrawingState = mCurrentState;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mTransactionPending = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mAnimTransactionPending = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//释放mTransactionCV, 如果SurfaceFlinger正在处理事务，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//而这时如果调用setTransactionState就可能会一直等着mTransactionCV, &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//因为setTransactionState可能会改变SurfaceFlinger的Transaction标志位，导致前后不一致&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mTransactionCV.broadcast();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这就是提交事务的操作，先处理pendingRemove的layer，回调onRemove接口；然后更新mDrawingState状态；最后释放mTransactionCV条件锁。    &lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;以上就是SurfaceFlinger处理事务的流程，接下来我们分析Layer怎么处理事务。&lt;/p&gt;
&lt;h1 id=&quot;Layer处理事务&quot;&gt;&lt;a href=&quot;#Layer处理事务&quot; class=&quot;headerlink&quot; title=&quot;Layer处理事务&quot;&gt;&lt;/a&gt;Layer处理事务&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在handleTransactionLocked函数中的Part1中，我们我们简要分析了layer处理自己事务的流程，接下来我们详细分析这个过程。&lt;/p&gt;
&lt;h2 id=&quot;Layer的重要变量&quot;&gt;&lt;a href=&quot;#Layer的重要变量&quot; class=&quot;headerlink&quot; title=&quot;Layer的重要变量&quot;&gt;&lt;/a&gt;Layer的重要变量&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们在&lt;a href=&quot;http://windrunnerlihuan.com/2017/06/17/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%85%AD-SurfaceFlinger%E5%88%9B%E5%BB%BASurface/&quot;&gt;Android SurfaceFlinger 学习之路(六)—-SurfaceFlinger创建Surface&lt;/a&gt;中提到过，每一个Layer都有很多属性。&lt;/p&gt;
&lt;p&gt; &amp;#160; &amp;#160; &amp;#160; &amp;#160;Each Layer has：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Z-order&lt;/li&gt;
&lt;li&gt;Alpha value from 0 to 255&lt;/li&gt;
&lt;li&gt;visibleRegion&lt;/li&gt;
&lt;li&gt;crop region&lt;/li&gt;
&lt;li&gt;transformation: rotate 0, 90, 180, 270: flip H, V: scale&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当多个Layer进行合成的时候，并不是整个Layer的空间都会被完全显示，根据这个Layer最终的显示效果，一个Layer可以被划分成很多的Region, Android SurfaceFlinger 定义了以下一些Region类型：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;TransparantRegion： 完全透明的区域，在它之下的区域将被显示出来。&lt;/li&gt;
&lt;li&gt;OpaqueRegion: 完全不透明的区域，是否显示取决于它上面是否有遮挡或是否透明。&lt;/li&gt;
&lt;li&gt;VisibleRegion: 可见区域，包括完全不透明无遮挡区域或半透明区域。&lt;/li&gt;
&lt;li&gt;visibleRegion = Region - above OpaqueRegion.&lt;/li&gt;
&lt;li&gt;CoveredRegion: 被遮挡区域，在它之上，有不透明或半透明区域。&lt;/li&gt;
&lt;li&gt;DirtyRegion: 可见部分改变区域，包括新的被遮挡区域，和新的露出区域。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们这里先看看以下几个重要属性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;State mCurrentState;&lt;br&gt;表示Layer下一帧的属性状态，当某个属性变化时，直接操作该变量&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;State mDrawingState;&lt;br&gt;表示当前正在绘制的帧的属性状态。Layer处理完事务后，最终的用于绘制的状态&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们再次看看Layer::State结构体的定义：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; State &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Geometry active;&lt;span class=&quot;comment&quot;&gt;//当前Layer的可见区域&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Geometry requested;&lt;span class=&quot;comment&quot;&gt;//请求的Layer的可见区域, 在Layer做doTransaction时会将 requested赋值给active. setSize/setMatrix/setPosition&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; z;&lt;span class=&quot;comment&quot;&gt;//z-order&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; layerStack;&lt;span class=&quot;comment&quot;&gt;//layerStack指明当前Layer属于哪个Display，Display的layer stack可以用 hw-&amp;gt;getLayerStack获得&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint8_t&lt;/span&gt; alpha;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint8_t&lt;/span&gt; flags;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint8_t&lt;/span&gt; reserved[&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;////当Layer的属性变化时， sequence就会加1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; sequence; &lt;span class=&quot;comment&quot;&gt;// changes when visible regions can change&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//更新region的传输矩阵&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Transform transform;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// the transparentRegion hint is a bit special, it&#39;s latched only&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// when we receive a buffer -- this is because it&#39;s &quot;content&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// dependent.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Region activeTransparentRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Region requestedTransparentRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id=&quot;doTransaction&quot;&gt;&lt;a href=&quot;#doTransaction&quot; class=&quot;headerlink&quot; title=&quot;doTransaction&quot;&gt;&lt;/a&gt;doTransaction&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们继续分析Layer处理事务的逻辑，看看Layer的doTransaction函数。&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;uint32_t Layer::doTransaction(uint32_t flags) &amp;#123;// 0&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //上一次绘制状态&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const Layer::State&amp;amp; s(getDrawingState());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //下一帧状态&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const Layer::State&amp;amp; c(getCurrentState());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //如果requested的可见区域与旧的可见区域不同了，则size changed&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const bool sizeChanged = (c.requested.w != s.requested.w) ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                             (c.requested.h != s.requested.h);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (sizeChanged) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // the size changed, we need to ask our client to request a new buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //省略一些log信息&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // record the new size, form this point on, when the client request&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // a buffer, it&#39;ll get the new size.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // 如果size changed, 把新的 w|h 设置到 BufferQueueCore中的 mDefaultWidth|mDefaultHeight中去&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSurfaceFlingerConsumer-&amp;gt;setDefaultBufferSize(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                c.requested.w, c.requested.h);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //如果新的请求的 w|h 与新的原本要显示的区域不同，表明是  resize了&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (!isFixedSize()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const bool resizePending = (c.requested.w != c.active.w) ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                   (c.requested.h != c.active.h);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (resizePending) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //resize只发生在非固定模式下&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // don&#39;t let Layer::doTransaction update the drawing state&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // if we have a pending resize, unless we are in fixed-size mode.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // the drawing state will be updated only once we receive a buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // with the correct size.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // in particular, we want to make sure the clip (which is part&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // of the geometry state) is latched together with the size but is&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // latched immediately when no resizing is involved.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //如果resize了，则打上eDontUpdateGeometryState的flag&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            flags |= eDontUpdateGeometryState;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // always set active to requested, unless we&#39;re asked not to&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // this is used by Layer, which special cases resizes.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (flags &amp;amp; eDontUpdateGeometryState)  &amp;#123;//skip&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; else &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //这里是允许更新 可见区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Layer::State&amp;amp; editCurrentState(getCurrentState());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        editCurrentState.active = c.requested;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //如果可见区域发生改变，刷新并重新计算可见区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (s.active != c.active) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // invalidate and recompute the visible regions if needed&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        flags |= Layer::eVisibleRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // 只要Layer有属性发生变化了，sequence就会加1,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //这样可以很直观判断是否当前的state和旧的state是否发生变化了&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // 但是这样并不能保证sequence相同，但是属性变化的这种情况&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (c.sequence != s.sequence) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // invalidate and recompute the visible regions if needed&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        flags |= eVisibleRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        this-&amp;gt;contentDirty = true;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // we may use linear filtering, if the matrix scales us&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const uint8_t type = c.transform.getType();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mNeedsFiltering = (!c.transform.preserveRects() ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                (type &amp;gt;= Transform::SCALE));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // Commit the transaction&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //提交事务&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    commitTransaction();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    return flags;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个函数长度还行，看着也不负责，流程如下：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）如果requested的可见区域与旧的可见区域不同了，则size changed。如果size changed, 把新的 w|h 设置到 BufferQueueCore中的 mDefaultWidth|mDefaultHeight中去。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里mSurfaceFlingerConsumer-&amp;gt;setDefaultBufferSize去设置变化后的大小，我们在&lt;a href=&quot;http://windrunnerlihuan.com/2017/06/17/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%85%AD-SurfaceFlinger%E5%88%9B%E5%BB%BASurface/&quot;&gt;Android SurfaceFlinger 学习之路(六)—-SurfaceFlinger创建Surface&lt;/a&gt;分析过mSurfaceFlingerConsumer的创建，位于Layer的onFirstRef函数中。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）如果可见区域发生改变，刷新并重新计算可见区域。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）sequence发生改变，重新获取大小。Sequence是个什么东西？当Layer的position，Zorder，alpha,matrix,transparent region,flags,crops.等发生变化的时候，sequence就会自增。也就是，当这些属性发生变化是，页面在Vsync信号触发的时候，根据sequence来判断是否需要属性页面。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）提交事务。主要就是同步2个state，将current state赋值给drawing state。看看代码如下：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; Layer::commitTransaction() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDrawingState = mCurrentState;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;以上就是SurfaceFlinger和Layer处理事务的逻辑。通俗的奖就是三句话：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;新增layer，对比2个state中的layer队列，就可以知道新增的layer。&lt;/li&gt;
&lt;li&gt;移除layer，也是比较2个layer队列，就可以找到移除的layer。&lt;/li&gt;
&lt;li&gt;提交transaction，主要就是同步2个state。然后currentstate继续跟踪layer变化，如此往复。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;贴个时序图就是下面的逻辑。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%B9%9D%29----SurfaceFlinger%E4%BA%8B%E5%8A%A1%E5%A4%84%E7%90%86/Transation.jpg&quot; alt=&quot;transation&quot;&gt;&lt;/p&gt;
&lt;h1 id=&quot;小结&quot;&gt;&lt;a href=&quot;#小结&quot; class=&quot;headerlink&quot; title=&quot;小结&quot;&gt;&lt;/a&gt;小结&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;以上就是SurfaceFlinger处理事务的简要流程。回顾开始的内容，我们说过SurfaceControl的openTransation和closeTransaction底层实现也是SurfaceFlinger处理事务的操作，不过这个我们以后在分析。下一篇就应该去讲Layer的合成了，也是个十分复杂的过程。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;断更三个月，期间也是尝尽辛酸苦辣，痛苦和悔恨只能自己默默下咽。只希望以后能够少点折腾，多一些安逸。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%B9%9D%29----SurfaceFlinger%E4%BA%8B%E5%8A%A1%E5%A4%84%E7%90%86/meizi.jpg&quot; alt=&quot;meizi&quot;&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;荒废三个月，终于更新了~这期间事情巨多，一言难尽~不过对SurfaceFlinger的研究不能停啊，还是要一点一点钻研。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这次继续顺着上次末尾，分析一下SurfaceFlinger事务处理。&lt;br&gt;
    
    </summary>
    
      <category term="Android技术点" scheme="http://windrunnerlihuan.com/categories/Android%E6%8A%80%E6%9C%AF%E7%82%B9/"/>
    
    
      <category term="SurfaceFlinger" scheme="http://windrunnerlihuan.com/tags/SurfaceFlinger/"/>
    
  </entry>
  
  <entry>
    <title>Android SurfaceFlinger 学习之路(八)----Surface管理图形缓冲区</title>
    <link href="http://windrunnerlihuan.com/2017/07/03/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%85%AB-Surface%E7%AE%A1%E7%90%86%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BA/"/>
    <id>http://windrunnerlihuan.com/2017/07/03/Android-SurfaceFlinger-学习之路-八-Surface管理图形缓冲区/</id>
    <published>2017-07-03T07:12:29.000Z</published>
    <updated>2019-01-06T07:29:07.591Z</updated>
    
    <content type="html">&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;本节我们学习一下上层app创建Surface到底层Surface管理图形缓冲区的简要过程，详细的从Activity到WMS最后至底层SurfaceFlinger消费surface我们以后再分析。&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;上层概述&quot;&gt;&lt;a href=&quot;#上层概述&quot; class=&quot;headerlink&quot; title=&quot;上层概述&quot;&gt;&lt;/a&gt;上层概述&lt;/h1&gt;&lt;h2 id=&quot;Surface概述&quot;&gt;&lt;a href=&quot;#Surface概述&quot; class=&quot;headerlink&quot; title=&quot;Surface概述&quot;&gt;&lt;/a&gt;Surface概述&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Surface也是个很复杂的系统，通过之前的学习，我们知道Surface相关的内容主要有两点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;应用程序和Surface的关系&lt;/li&gt;
&lt;li&gt;Surface和SurfaceFlinger之间的关系&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;通过之前对SurfaceFlinger系统的概述，大概用如下图表示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%85%AB%29----Surface%E7%AE%A1%E7%90%86%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BA/app.jpg&quot; alt=&quot;app&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;(右图合成不止有OpenGL，还有HWC硬件，这个我们图中没有画出)&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;先看左图。可以发现，不论是使用Skia绘制二维图像，还是用OpenGL绘制三维图像，最终Application都要和Surface交互。Surface就像是UI的画布，而App则像是在Surface上作画。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;再看右图。Surface和SurfaceFlinger的关系，Surface向SurfaceFlinger提供数据，而SurfaceFlinger则混合数据。其实就是调用OpenGL ES库中的EGL去合成（或者HWC硬件），然后在FrameBuffer上渲染。&lt;/p&gt;
&lt;h2 id=&quot;简述Activity显示&quot;&gt;&lt;a href=&quot;#简述Activity显示&quot; class=&quot;headerlink&quot; title=&quot;简述Activity显示&quot;&gt;&lt;/a&gt;简述Activity显示&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;(这一部分我们以后会详细分析，这里因为后面分析surface需要用到，所以简单提一下)&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;一般来说，应用程序的外表是通过Activity来展示的。那么，Activity是如何完成界面绘制工作的呢？根据前面所讲的知识，应用程序的显示和Surface有关，那么具体到Activity上，它和Surface又是什么关系呢？因为我们只是提一下，所以用两幅巨图来表示：&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Android 应用程序是怎么创建出来的，大概的流程是 ActivityManagerService -&amp;gt; Zygote -&amp;gt; Fork App,。一个新的应用被fork完后，第一个调用的方法就是 ActivityThread的main()，这个函数主要做的事情就是创建一个ActivityThread线程，然后调用loop()开始等待。当收到来自 ActivityManager 的 LAUNCH_ACTIVITY 消息后，Activity开始了他的显示之旅。下图描绘的是Activity在显示前的准备流程：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%85%AB%29----Surface%E7%AE%A1%E7%90%86%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BA/activity.png&quot; alt=&quot;activity&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们可以说，一个应用可以有多个Activity，每个 Activity 一个Window(PhoneWindow)， 每个Window 有一个DecorView, 一个ViewRootImpl, 对应在WindowManagerService 里有一个Window(WindowState)。我们再看另一幅巨图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%85%AB%29----Surface%E7%AE%A1%E7%90%86%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BA/activity2.png&quot; alt=&quot;activity2&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;ViewRootImpl 在整个Android的GUI系统中占据非常重要的位置，如果把Activity和View 看作 ‘MVC’ 中的V, 把各种后台服务看作Modal，ViewRootImpl 则是’MVC’ 中的’C’ - Controller. Controller在MVC架构里承担着承上启下的作用，一般来说它的逻辑最为复杂。从下图可以看到，ViewRootImpl 与 用户输入系统(接收用户按键，触摸屏输入), 窗口系统（复杂窗口的布局，刷新，动画），显示合成系统（包括定时器Choreograph, SurfaceFlinger), 乃至Audio系统（音效输出）等均有密切的关联。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%85%AB%29----Surface%E7%AE%A1%E7%90%86%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BA/viewroot.png&quot; alt=&quot;viewroot&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;关于创建一Surface的简要时序图可以如下表示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%85%AB%29----Surface%E7%AE%A1%E7%90%86%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BA/Surface.jpg&quot; alt=&quot;Surface&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;应用层创建Surface上面时序图已经列出了，即：ViewRootImpl通过Session向WindowMangerService简历通信回话，然后请求WindowManagerService调用relayoutWindow方法，在方法内部通过WindowStateAnimator创建一个SurfaceControl，然后将ViewRootImpl中的无参构造的Surface通过调用copyFrom在JNI层创建一个Surface，并返回句柄给java层。（&lt;strong&gt;只是简述，后面章节在分析&lt;/strong&gt;）相关方法如下：&lt;br&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/*WindowManagerService的relayoutWindow方法*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;relayoutWindow&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(Session session, IWindow client, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; seq,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            WindowManager.LayoutParams attrs, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; requestedWidth,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; requestedHeight, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; viewVisibility, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; flags,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Rect outVisibleInsets, Rect outStableInsets, Configuration outConfig,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Surface outSurface)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//这个最后的参数outSurface就是ViewRootImpl的无参构造方法创建的对象&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//private final Surface mSurface = new Surface();&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//调用WindowStateAnimator的createSurfaceLocked方法创建一个SurfaceControl&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (surfaceControl != &lt;span class=&quot;keyword&quot;&gt;null&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;//调用Surface的copyFrom方法，在JNI层构造一个Surface&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        outSurface.copyFrom(surfaceControl);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (SHOW_TRANSACTIONS) Slog.i(TAG,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                &lt;span class=&quot;string&quot;&gt;&quot;  OUT SURFACE &quot;&lt;/span&gt; + outSurface + &lt;span class=&quot;string&quot;&gt;&quot;: copied&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// For some reason there isn&#39;t a surface.  Clear the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// caller&#39;s object so they see the same state.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        outSurface.release();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ......       &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;SurfaceControl &lt;span class=&quot;title&quot;&gt;createSurfaceLocked&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...省略其他步骤...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//这个构造方法第一个参数SurfaceSession就是SurfaceComposerClient在java层的代表&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceControl = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; SurfaceControl(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        mSession.mSurfaceSession,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        attrs.getTitle().toString(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        width, height, format, flags);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...省略其他步骤...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mSurfaceControl;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们从&lt;a href=&quot;http://windrunnerlihuan.com/2017/06/17/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%85%AD-SurfaceFlinger%E5%88%9B%E5%BB%BASurface/&quot;&gt;Android SurfaceFlinger 学习之路(六)—-SurfaceFlinger创建Surface&lt;/a&gt;得知应用层创建Surface对应在SurfaceFlinger这边就是一个Layer，而这个Layer是由SurfaceFlinger创建的。所以我们上面创建java层Surface也需要拿到SurfaceFlinger服务的客户端代理才行。这个代理就是SurfaceSession类对象，mSession.mSurfaceSession。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;它的创建是构造ViewRootImpl时候，调用WindowManagerGlobal的getWindowSession方法，通过WMS的代理创建openSession创建一个Session回话。然后ViewRootImpl的setView方法，方法内通过WMS代理调用WMS的addWindow方法，里面利用Session对象调用windowAddedLocked方法创建一个SurfaceSession。&lt;strong&gt;这就是它的流程，我们仅仅简单描述&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面就是Activity创建Surface的java层简要过程。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;关于绘制这个流程很复杂，我们后续章节在分析。&lt;/strong&gt;这里我们因为要分析Surface机制，所以只分析ViewRootImpl的draw流程。（如果开启了硬件加速功能，则会使用hwui硬件绘制功能，这里我们忽略这个，使用默认的软件绘制流程drawSoftware）位于frameworks/base/core/java/android/view/ViewRootImpl.java：&lt;br&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt; Surface mSurface = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Surface();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;drawSoftware&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(Surface surface, AttachInfo attachInfo, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; xoff, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; yoff,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;boolean&lt;/span&gt; scalingRequired, Rect dirty)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Draw with software renderer.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt; Canvas canvas;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;try&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; left = dirty.left;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; top = dirty.top;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; right = dirty.right;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; bottom = dirty.bottom;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        canvas = mSurface.lockCanvas(dirty);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mView.draw(canvas);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        surface.unlockCanvasAndPost(canvas); &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们核心就是这三行代码，这里中间的mView.draw(canvas);这个是调用skia图形库的绘制流程。&lt;strong&gt;我们暂时不分析，因为我们不关注这个绘制流程&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们主要分析canvas = mSurface.lockCanvas(dirty);和surface.unlockCanvasAndPost(canvas);的流程。这两个关系到我们下面的图形缓冲区的管理。&lt;/p&gt;
&lt;h2 id=&quot;Surface的JNI调用&quot;&gt;&lt;a href=&quot;#Surface的JNI调用&quot; class=&quot;headerlink&quot; title=&quot;Surface的JNI调用&quot;&gt;&lt;/a&gt;Surface的JNI调用&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们分别分析Surface的构建还有lockCanvas还有unlockCanvasAndPost方法。&lt;/p&gt;
&lt;h3 id=&quot;Surface的构造&quot;&gt;&lt;a href=&quot;#Surface的构造&quot; class=&quot;headerlink&quot; title=&quot;Surface的构造&quot;&gt;&lt;/a&gt;Surface的构造&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;其实看到上面代码，让我们想起来java层构建Surface和在&lt;a href=&quot;http://windrunnerlihuan.com/2017/06/17/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%85%AD-SurfaceFlinger%E5%88%9B%E5%BB%BASurface/&quot;&gt;Android SurfaceFlinger 学习之路(六)—-SurfaceFlinger创建Surface&lt;/a&gt;分析的native层创建Surface流程基本一样，也是先创建一个SurfaceControl，然后利用SurfaceControl创建Surface。我们分部查看这个过程。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）因为创建SurfaceControl，在native层需要SurfaceFlinger服务，所以我们看看java层如何获取SurfaceFlinger服务。所以我们看看上面讲到的创建SurfaceSession，位于frameworks/base/core/java/android/view/SurfaceSession.java：&lt;br&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// Note: This field is accessed by native code.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;long&lt;/span&gt; mNativeClient; &lt;span class=&quot;comment&quot;&gt;// SurfaceComposerClient*&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;native&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;nativeCreate&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/** Create a new connection with the surface flinger. */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;SurfaceSession&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mNativeClient = nativeCreate();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt; &amp;#160; &amp;#160; &amp;#160; &amp;#160;对于JNI层位于frameworks/base/core/jni/android_view_SurfaceSession.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; jlong &lt;span class=&quot;title&quot;&gt;nativeCreate&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(JNIEnv* env, jclass clazz)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//SurfaceComposerClient专门用来和surfaceflinger建立connection（ISurfaceComposerClient）&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    SurfaceComposerClient* client = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; SurfaceComposerClient();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    client-&amp;gt;incStrong((&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;*)nativeCreate);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;jlong&amp;gt;(client);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceComposerClient专门用来和surfaceflinger建立connection（ISurfaceComposerClient） ，SurfaceComposerClient是client，而surface flinger中的server为Client，SurfaceSession就是SurfaceComposerClient在java层的代表，其mNativeClient 成员就是native层的SurfaceComposerClient对象的指针。这一部分可以查看&lt;a href=&quot;http://windrunnerlihuan.com/2017/05/13/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%9B%9B-SurfaceFlinger%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%90%AF%E5%8A%A8%E4%B8%8E%E8%BF%9E%E6%8E%A5%E8%BF%87%E7%A8%8B/&quot;&gt;Android SurfaceFlinger 学习之路(四)—-SurfaceFlinger服务的启动与连接过程&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）然后我们该看看java层SurfaceControl的创建了，位于frameworks/native/libs/gui/SurfaceControl.java：&lt;br&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;SurfaceControl&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(SurfaceSession session,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        String name, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; h, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; format, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; flags)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;throws&lt;/span&gt; OutOfResourcesException &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mName = name;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//调用nativeCreate本地方法&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mNativeObject = nativeCreate(session, name, w, h, format, flags);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt; String mName;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;long&lt;/span&gt; mNativeObject; &lt;span class=&quot;comment&quot;&gt;// package visibility only for Surface.java access&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;native&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;nativeCreate&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(SurfaceSession session, String name,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; h, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; format, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; flags)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;throws&lt;/span&gt; OutOfResourcesException&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;nativeCreate方法对应于JNI层位于frameworks/base/core/jni/android_view_SurfaceControl.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; jlong &lt;span class=&quot;title&quot;&gt;nativeCreate&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(JNIEnv* env, jclass clazz, jobject sessionObj,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        jstring nameStr, jint w, jint h, jint format, jint flags)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;ScopedUtfChars &lt;span class=&quot;title&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(env, nameStr)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;SurfaceComposerClient&amp;gt; client(android_view_SurfaceSession_getClient(env, sessionObj));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;SurfaceControl&amp;gt; surface = client-&amp;gt;createSurface(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            String8(name.c_str()), w, h, format, flags);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (surface == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        jniThrowException(env, OutOfResourcesException, &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    surface-&amp;gt;incStrong((&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; *)nativeCreate);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;jlong&amp;gt;(surface.get());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里在JNI层调用上面创建的SurfaceComposerClient对象的createSurface函数，请求SurfaceFlinger去创建一个Layer，然后将这些信息封装成一个SurfaceControl。这一部分我们之前讲过，可以参考&lt;a href=&quot;http://windrunnerlihuan.com/2017/06/17/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%85%AD-SurfaceFlinger%E5%88%9B%E5%BB%BASurface/&quot;&gt;Android SurfaceFlinger 学习之路(六)—-SurfaceFlinger创建Surface&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）最后就是Surface的copyFrom方法，从SurfaceControl获取Surface信息。位于frameworks/base/core/java/android/view/Surface.java：&lt;br&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;copyFrom&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(SurfaceControl other)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (other == &lt;span class=&quot;keyword&quot;&gt;null&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; IllegalArgumentException(&lt;span class=&quot;string&quot;&gt;&quot;other must not be null&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;long&lt;/span&gt; surfaceControlPtr = other.mNativeObject;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (surfaceControlPtr == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; NullPointerException(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;string&quot;&gt;&quot;SurfaceControl native object is null. Are you using a released SurfaceControl?&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;long&lt;/span&gt; newNativeObject = nativeCreateFromSurfaceControl(surfaceControlPtr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;synchronized&lt;/span&gt; (mLock) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mNativeObject != &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            nativeRelease(mNativeObject);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        setNativeObjectLocked(newNativeObject);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;对应的JNI层调用位于frameworks/base/core/jni/android_view_Surface.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; jlong &lt;span class=&quot;title&quot;&gt;nativeCreateFromSurfaceControl&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(JNIEnv* env, jclass clazz,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        jlong surfaceControlNativeObj)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * This is used by the WindowManagerService just after constructing&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * a Surface and is necessary for returning the Surface reference to&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * the caller. At this point, we should only have a SurfaceControl.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;SurfaceControl&amp;gt; ctrl(&lt;span class=&quot;keyword&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;SurfaceControl *&amp;gt;(surfaceControlNativeObj));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//调用SurfaceControl的getSurface函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;Surface&amp;gt; surface(ctrl-&amp;gt;getSurface());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (surface != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        surface-&amp;gt;incStrong(&amp;amp;sRefBaseOwner);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;jlong&amp;gt;(surface.get());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;先从java层保存c++层SurfaceControl的long型句柄，获取C++层SurfaceControl，然后调用其getSurface函数创建一个Surface，最后将这个Surface的句柄通过JNI回传给java层保存。这个getSurface函数我们以前讲过，可以查看&lt;a href=&quot;http://windrunnerlihuan.com/2017/06/17/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%85%AD-SurfaceFlinger%E5%88%9B%E5%BB%BASurface/&quot;&gt;Android SurfaceFlinger 学习之路(六)—-SurfaceFlinger创建Surface&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;至此我们的Surface的创建就完成了。&lt;/p&gt;
&lt;h3 id=&quot;lockCanvas&quot;&gt;&lt;a href=&quot;#lockCanvas&quot; class=&quot;headerlink&quot; title=&quot;lockCanvas&quot;&gt;&lt;/a&gt;lockCanvas&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们接着回到ViewRootImpl的drawSoftware方法，按步骤来，先卡看Surface的lockCanvas方法，位于frameworks/base/core/java/android/view/Surface.java：&lt;br&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//mCanvas 变量直接赋值&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt; Canvas mCanvas = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; CompatibleCanvas();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; Canvas &lt;span class=&quot;title&quot;&gt;lockCanvas&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(Rect inOutDirty)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;throws&lt;/span&gt; Surface.OutOfResourcesException, IllegalArgumentException &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;synchronized&lt;/span&gt; (mLock) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        checkNotReleasedLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mLockedObject != &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// Ideally, nativeLockCanvas() would throw in this situation and prevent the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// double-lock, but that won&#39;t happen if mNativeObject was updated.  We can&#39;t&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// abandon the old mLockedObject because it might still be in use, so instead&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// we just refuse to re-lock the Surface.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; IllegalArgumentException(&lt;span class=&quot;string&quot;&gt;&quot;Surface was already locked&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mLockedObject = nativeLockCanvas(mNativeObject, mCanvas, inOutDirty);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mCanvas;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;老路子，继续查看JNI代码，位于frameworks/base/core/jni/android_view_Surface.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; jlong &lt;span class=&quot;title&quot;&gt;nativeLockCanvas&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(JNIEnv* env, jclass clazz,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        jlong nativeObject, jobject canvasObj, jobject dirtyRectObj)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//获取java层的Surface保存的long型句柄&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;Surface&amp;gt; surface(&lt;span class=&quot;keyword&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;Surface *&amp;gt;(nativeObject));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!isSurfaceValid(surface)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        doThrowIAE(env);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Rect dirtyRect;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Rect* dirtyRectPtr = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//获取java层dirty Rect的位置大小信息&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (dirtyRectObj) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dirtyRect.left   = env-&amp;gt;GetIntField(dirtyRectObj, gRectClassInfo.left);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dirtyRect.top    = env-&amp;gt;GetIntField(dirtyRectObj, gRectClassInfo.top);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dirtyRect.right  = env-&amp;gt;GetIntField(dirtyRectObj, gRectClassInfo.right);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dirtyRect.bottom = env-&amp;gt;GetIntField(dirtyRectObj, gRectClassInfo.bottom);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dirtyRectPtr = &amp;amp;dirtyRect;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ANativeWindow_Buffer outBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//调用Surface的lock方法,将申请的图形缓冲区赋给outBuffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = surface-&amp;gt;lock(&amp;amp;outBuffer, dirtyRectPtr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt;* &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; exception = (err == NO_MEMORY) ?&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                OutOfResourcesException :&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;string&quot;&gt;&quot;java/lang/IllegalArgumentException&quot;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        jniThrowException(env, exception, &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Associate a SkCanvas object to this surface&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//给java层的Canvas对象的mSurfaceFormat变量赋值。&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//Java的Surface对象构造的时候会创建一个CompatibleCanvas&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    env-&amp;gt;SetIntField(canvasObj, gCanvasClassInfo.mSurfaceFormat, outBuffer.format);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//创建一个SkImageInfo ，用于下面创建SkBitmap &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    SkImageInfo info = SkImageInfo::Make(outBuffer.width, outBuffer.height,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                         convertPixelFormat(outBuffer.format),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                         kPremul_SkAlphaType);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (outBuffer.format == PIXEL_FORMAT_RGBX_8888) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        info.fAlphaType = kOpaque_SkAlphaType;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    SkBitmap bitmap;&lt;span class=&quot;comment&quot;&gt;//创建一个SkBitmap &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//图形缓冲区每一行像素大小&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;ssize_t&lt;/span&gt; bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    然后填充SkBitmap相关变量&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    bitmap.setInfo(info, bpr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (outBuffer.width &amp;gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; &amp;amp;&amp;amp; outBuffer.height &amp;gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//outBuffer.bits指向一块存储区域&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        bitmap.setPixels(outBuffer.bits);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// be safe with an empty bitmap.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        bitmap.setPixels(&lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//调用Java层Canvas的setNativeBitmap方法，保存JNI层构建的SkBitmap&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    env-&amp;gt;CallVoidMethod(canvasObj, gCanvasClassInfo.setNativeBitmap,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;jlong&amp;gt;(&amp;amp;bitmap));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (dirtyRectPtr) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//剪裁出dirty区域大小&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        SkCanvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        nativeCanvas-&amp;gt;clipRect( SkRect::Make(&lt;span class=&quot;keyword&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; SkIRect&amp;amp;&amp;gt;(dirtyRect)) );&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (dirtyRectObj) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//将剪裁位置大小信息赋给java层Canvas对象&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        env-&amp;gt;SetIntField(dirtyRectObj, gRectClassInfo.left,   dirtyRect.left);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        env-&amp;gt;SetIntField(dirtyRectObj, gRectClassInfo.top,    dirtyRect.top);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        env-&amp;gt;SetIntField(dirtyRectObj, gRectClassInfo.right,  dirtyRect.right);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        env-&amp;gt;SetIntField(dirtyRectObj, gRectClassInfo.bottom, dirtyRect.bottom);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Create another reference to the surface and return it.  This reference&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// should be passed to nativeUnlockCanvasAndPost in place of mNativeObject,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// because the latter could be replaced while the surface is locked.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;Surface&amp;gt; lockedSurface(surface);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    lockedSurface-&amp;gt;incStrong(&amp;amp;sRefBaseOwner);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; (jlong) lockedSurface.get();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这段代码逻辑主要如下：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）获取java层dirty 的Rect大小和位置信息；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）调用Surface的lock方法,将申请的图形缓冲区赋给outBuffer；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）创建一个Skbitmap，填充它用来保存申请的图形缓冲区，并赋值给Java层的Canvas对象；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）将剪裁位置大小信息赋给java层Canvas对象。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们关注的核心就是在第二步申请图形缓冲区，这个我们下面会分析到。&lt;/p&gt;
&lt;h3 id=&quot;unlockCanvasAndPost&quot;&gt;&lt;a href=&quot;#unlockCanvasAndPost&quot; class=&quot;headerlink&quot; title=&quot;unlockCanvasAndPost&quot;&gt;&lt;/a&gt;unlockCanvasAndPost&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们跳过draw过程，不分析这个，所以到了最后一步，Surface绘制完毕后，unlockCanvasAndPost操作。&lt;br&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;unlockCanvasAndPost&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(Canvas canvas)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (canvas != mCanvas) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; IllegalArgumentException(&lt;span class=&quot;string&quot;&gt;&quot;canvas object must be the same instance that &quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                + &lt;span class=&quot;string&quot;&gt;&quot;was previously returned by lockCanvas&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;synchronized&lt;/span&gt; (mLock) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        checkNotReleasedLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mNativeObject != mLockedObject) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Log.w(TAG, &lt;span class=&quot;string&quot;&gt;&quot;WARNING: Surface&#39;s mNativeObject (0x&quot;&lt;/span&gt; +&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    Long.toHexString(mNativeObject) + &lt;span class=&quot;string&quot;&gt;&quot;) != mLockedObject (0x&quot;&lt;/span&gt; +&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    Long.toHexString(mLockedObject) +&lt;span class=&quot;string&quot;&gt;&quot;)&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mLockedObject == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; IllegalStateException(&lt;span class=&quot;string&quot;&gt;&quot;Surface was not locked&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;try&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            nativeUnlockCanvasAndPost(mLockedObject, canvas);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;finally&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            nativeRelease(mLockedObject);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mLockedObject = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;依然查看JNI层代码，位于frameworks/base/core/jni/android_view_Surface.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;nativeUnlockCanvasAndPost&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(JNIEnv* env, jclass clazz,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        jlong nativeObject, jobject canvasObj)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//获取java层的Surface保存的long型句柄&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;Surface&amp;gt; surface(&lt;span class=&quot;keyword&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;Surface *&amp;gt;(nativeObject));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!isSurfaceValid(surface)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// detach the canvas from the surface&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//接触java层对native层SkBitmap的引用&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    env-&amp;gt;CallVoidMethod(canvasObj, gCanvasClassInfo.setNativeBitmap, (jlong)&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// unlock surface&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//调用native层Surface的unlockAndPost函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = surface-&amp;gt;unlockAndPost();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        doThrowIAE(env);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个代码依然很简单，核心就是调用native层Surface的unlockAndPost函数。我们接下来会分析。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;综上这个流程大概是如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%85%AB%29----Surface%E7%AE%A1%E7%90%86%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BA/surfacecycle.jpg&quot; alt=&quot;surfacecycle&quot;&gt;&lt;/p&gt;
&lt;h1 id=&quot;Surface管理图形缓冲区&quot;&gt;&lt;a href=&quot;#Surface管理图形缓冲区&quot; class=&quot;headerlink&quot; title=&quot;Surface管理图形缓冲区&quot;&gt;&lt;/a&gt;Surface管理图形缓冲区&lt;/h1&gt;&lt;h2 id=&quot;Surface申请图形缓冲区&quot;&gt;&lt;a href=&quot;#Surface申请图形缓冲区&quot; class=&quot;headerlink&quot; title=&quot;Surface申请图形缓冲区&quot;&gt;&lt;/a&gt;Surface申请图形缓冲区&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们上边分析到了申请图形缓冲区，用到了Surface的lock函数，我们继续查看，位于frameworks/native/libs/gui/Surface.cpp：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;96&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;97&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;98&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;99&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;100&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;101&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;102&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;103&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;104&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;105&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;106&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;107&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;108&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;109&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;110&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;111&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;112&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;113&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;114&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;115&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;status_t Surface::lock(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (mLockedBuffer != 0) &amp;#123;//还没有lock&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&quot;Surface::lock failed, already locked&quot;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        return INVALID_OPERATION;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (!mConnectedToCpu) &amp;#123;//false&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //调用connect函数完成一些初始化&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        int err = Surface::connect(NATIVE_WINDOW_API_CPU);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (err) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            return err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // we&#39;re intending to do software rendering from this point&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //设置GRALLOC_USAGE_SW_READ_OFTEN 和GRALLOC_USAGE_SW_WRITE_OFTEN标志位，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //表示打算使用软件渲染&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ANativeWindowBuffer* out;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    int fenceFd = -1;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //调用dequeueBuffer函数，申请图形缓冲区&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    status_t err = dequeueBuffer(&amp;amp;out, &amp;amp;fenceFd);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGE_IF(err, &quot;dequeueBuffer failed (%s)&quot;, strerror(-err));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (err == NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //获取图形缓冲区区域大小,赋给后备缓冲区变量backBuffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;GraphicBuffer&amp;gt; backBuffer(GraphicBuffer::getSelf(out));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const Rect bounds(backBuffer-&amp;gt;width, backBuffer-&amp;gt;height);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Region newDirtyRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (inOutDirtyBounds) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //如果上层指定乐刷新脏矩形区域，则用这个区域和缓冲区区域求交集，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //然后将交集的结果设给需要去刷新的新区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            newDirtyRegion.set(static_cast&amp;lt;Rect const&amp;amp;&amp;gt;(*inOutDirtyBounds));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //与运算，求交集&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            newDirtyRegion.andSelf(bounds);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; else &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //如果上层没有指定脏矩形区域，所以刷新整个图形缓冲区&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            newDirtyRegion.set(bounds);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // figure out if we can copy the frontbuffer back&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //上一次绘制的信息保存在mPostedBuffer中，而这个mPostedBuffer则要在unLockAndPost函数中设置&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const sp&amp;lt;GraphicBuffer&amp;gt;&amp;amp; frontBuffer(mPostedBuffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const bool canCopyBack = (frontBuffer != 0 &amp;amp;&amp;amp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                backBuffer-&amp;gt;width  == frontBuffer-&amp;gt;width &amp;amp;&amp;amp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                backBuffer-&amp;gt;height == frontBuffer-&amp;gt;height &amp;amp;&amp;amp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                backBuffer-&amp;gt;format == frontBuffer-&amp;gt;format);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (canCopyBack) &amp;#123;//如果后备缓冲区大小和上次绘制缓冲区大小一样，则不用更新整个buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // copy the area that is invalid and not repainted this round&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //将需要更新的dirty区域剪裁出来，剩余的不需要更新的区域我们不用重绘&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //附注：mDirtyRegion变量命名在老版本Android是mOldDirtyRegion，指的是上一次绘制的dirty区域&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const Region copyback(mDirtyRegion.subtract(newDirtyRegion));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (!copyback.isEmpty())&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //这里把mPostedBuffer中的旧数据拷贝到BackBuffer中。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //后续的绘画只要更新脏区域就可以了，这会节约不少资源&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                copyBlt(backBuffer, frontBuffer, copyback);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; else &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // if we can&#39;t copy-back anything, modify the user&#39;s dirty&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // region to make sure they redraw the whole buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //如果两次图形缓冲区大小不一致，我们就要修改用户指定的dirty区域大小为整个缓冲区大小，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //然后去更新整个缓冲区&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            newDirtyRegion.set(bounds);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mDirtyRegion.clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Mutex::Autolock lock(mMutex);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            for (size_t i=0 ; i&amp;lt;NUM_BUFFER_SLOTS ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mSlots[i].dirtyRegion.clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#123; // scope for the lock&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Mutex::Autolock lock(mMutex);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //得到此次后备缓冲器的bufferSlot在mSlots里面的index&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            int backBufferSlot(getSlotFromBufferLocked(backBuffer.get()));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (backBufferSlot &amp;gt;= 0) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //将新的dirty赋给这个bufferslot&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                Region&amp;amp; dirtyRegion(mSlots[backBufferSlot].dirtyRegion);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mDirtyRegion.subtract(dirtyRegion);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                dirtyRegion = newDirtyRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //然后再加上新的dirty区域，或运算，相叠加&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mDirtyRegion.orSelf(newDirtyRegion);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (inOutDirtyBounds) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            *inOutDirtyBounds = newDirtyRegion.getBounds();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        void* vaddr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //lock和unlock分别用来锁定和解锁一个指定的图形缓冲区，在访问一块图形缓冲区的时候，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //例如，向一块图形缓冲写入内容的时候，需要将该图形缓冲区锁定，用来避免访问冲突,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //锁定之后，就可以获得由参数参数l、t、w和h所圈定的一块缓冲区的起始地址，保存在输出参数vaddr中&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        status_t res = backBuffer-&amp;gt;lockAsync(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                newDirtyRegion.bounds(), &amp;amp;vaddr, fenceFd);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGW_IF(res, &quot;failed locking buffer (handle = %p)&quot;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                backBuffer-&amp;gt;handle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (res != 0) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            err = INVALID_OPERATION;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; else &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //相关赋值&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mLockedBuffer = backBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            outBuffer-&amp;gt;width  = backBuffer-&amp;gt;width;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            outBuffer-&amp;gt;height = backBuffer-&amp;gt;height;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            outBuffer-&amp;gt;stride = backBuffer-&amp;gt;stride;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            outBuffer-&amp;gt;format = backBuffer-&amp;gt;format;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            outBuffer-&amp;gt;bits   = vaddr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    return err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Surface的lock函数用来申请图形缓冲区和一些操作，方法不长，大概工作有：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）调用connect函数完成一些初始化；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）调用dequeueBuffer函数，申请图形缓冲区；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）计算需要绘制的新的dirty区域，旧的区域原样copy数据。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在大部分情况下，UI只有一小部分会发生变化（例如一个按钮被按下去，导致颜色发生变化），这一小部分UI只对应整个GraphicBuffer中的一小块存储（就是在前面代码中见到的dirtyRegion），如果整块存储都更新，则会极大地浪费资源。怎么办？&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这就需要将变化的图像和没有发生变化的图像进行叠加。上一次绘制的信息保存在mPostedBuffer中，而这个mPostedBuffer则要在unLockAndPost函数中设置。这里将根据需要，把mPostedBuffer中的旧数据拷贝到BackBuffer中。后续的绘画只要更新脏区域就可以了，这会节约不少资源。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）lock和unlock分别用来锁定和解锁一个指定的图形缓冲区，在访问一块图形缓冲区的时候，例如，向一块图形缓冲写入内容的时候，需要将该图形缓冲区锁定，用来避免访问冲突,锁定之后，就可以获得由参数参数l、t、w和h所圈定的一块缓冲区的起始地址，保存在输出参数vaddr中。另一方面，在访问完成一块图形缓冲区之后，需要解除这块图形缓冲区的锁定。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;其他步骤都已经在注释里说明了，我们主要看看那第二步，dequeueBuffer函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; Surface::dequeueBuffer(&lt;span class=&quot;keyword&quot;&gt;android_native_buffer_t&lt;/span&gt;** buffer, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;* fenceFd) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGV(&lt;span class=&quot;string&quot;&gt;&quot;Surface::dequeueBuffer&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; reqW;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; reqH;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; swapIntervalZero;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; reqFormat;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; reqUsage;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        reqW = mReqWidth ? mReqWidth : mUserWidth;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        reqH = mReqHeight ? mReqHeight : mUserHeight;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        swapIntervalZero = mSwapIntervalZero;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        reqFormat = mReqFormat;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        reqUsage = mReqUsage;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;comment&quot;&gt;// Drop the lock so that we can still touch the Surface while blocking in IGBP::dequeueBuffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; buf = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;Fence&amp;gt; fence;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//申请图形缓冲区，我们上一节分析过这个过程&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; result = mGraphicBufferProducer-&amp;gt;dequeueBuffer(&amp;amp;buf, &amp;amp;fence, swapIntervalZero,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            reqW, reqH, reqFormat, reqUsage);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (result &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGV(&lt;span class=&quot;string&quot;&gt;&quot;dequeueBuffer: IGraphicBufferProducer::dequeueBuffer(%d, %d, %d, %d, %d)&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             &lt;span class=&quot;string&quot;&gt;&quot;failed: %d&quot;&lt;/span&gt;, swapIntervalZero, reqW, reqH, reqFormat, reqUsage,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             result);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; result;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//根据index获取缓冲区&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;GraphicBuffer&amp;gt;&amp;amp; gbuf(mSlots[buf].buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// this should never happen&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGE_IF(fence == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&quot;Surface::dequeueBuffer: received null Fence! buf=%d&quot;&lt;/span&gt;, buf);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//上一篇分析过，如果所有状态buffer的个数大于64，就要释放所有超过64的buffer，并贴上RELEASE_ALL_BUFFERS标志位&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (result &amp;amp; IGraphicBufferProducer::RELEASE_ALL_BUFFERS) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        freeAllBuffers();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//增加BUFFER_NEEDS_REALLOCATION标志，已重新分配GraphicBuffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((result &amp;amp; IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//由于申请的内存是在surfaceflinger进程中，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//BufferQueue中的图形缓冲区也是通过匿名共享内存和binder传递描述符映射过去的，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//Surface通过调用requestBuffer将图形缓冲区映射到Surface所在进程&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        result = mGraphicBufferProducer-&amp;gt;requestBuffer(buf, &amp;amp;gbuf);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (result != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: %d&quot;&lt;/span&gt;, result);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mGraphicBufferProducer-&amp;gt;cancelBuffer(buf, fence);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; result;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (fence-&amp;gt;isValid()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        *fenceFd = fence-&amp;gt;dup();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (*fenceFd == &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;dequeueBuffer: error duping fence: %d&quot;&lt;/span&gt;, errno);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// dup() should never fail; something is badly wrong. Soldier on&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// and hope for the best; the worst that should happen is some&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// visible corruption that lasts until the next frame.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        *fenceFd = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//获取这个这个buffer对象的指针内容&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    *buffer = gbuf.get();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; OK;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;首先调用BufferQueueProducer的dequeueBuffer函数申请一块图形缓冲区，这个我们上一节讲过，&lt;a href=&quot;http://windrunnerlihuan.com/2017/06/22/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B8%83-%E5%88%9B%E5%BB%BA%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BAGraphicBuffer/&quot;&gt;Android SurfaceFlinger 学习之路(七)—-创建图形缓冲区GraphicBuffer&lt;/a&gt;。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;先在mSlot数组中查找FREE状态的slot，如果找到了就返回这个slot中的index。这个操作是调用了waitForFreeSlotThenRelock函数。如果没有找到，就要从匿名共享内存中重新分配。重新分配返回的flag会加上BUFFER_NEEDS_REALLOCATION标志位。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果是在匿名共享内存中重新分配的，就要根据index调用BufferQueueProducer的requestBuffer去获取mSlots数组中的bufferSlot，然后取出slot中的buffer。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;最后就是将取到的Buffer返回。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们上一篇没有分析BufferQueueProducer的requestBuffer，也是通过IPC Binder调用远程接口，省去这个过程，直接看实现，位于frameworks/native/libs/gui/BufferQueueProducer.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; BufferQueueProducer::requestBuffer(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; slot, sp&amp;lt;GraphicBuffer&amp;gt;* buf) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BQ_LOGV(&lt;span class=&quot;string&quot;&gt;&quot;requestBuffer: slot %d&quot;&lt;/span&gt;, slot);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mCore-&amp;gt;mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mCore-&amp;gt;mIsAbandoned) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        BQ_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;requestBuffer: BufferQueue has been abandoned&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_INIT;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//check index and state&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (slot &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; || slot &amp;gt;= BufferQueueDefs::NUM_BUFFER_SLOTS) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        BQ_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;requestBuffer: slot index %d out of range [0, %d)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                slot, BufferQueueDefs::NUM_BUFFER_SLOTS);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; BAD_VALUE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        BQ_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;requestBuffer: slot %d is not owned by the producer &quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;string&quot;&gt;&quot;(state = %d)&quot;&lt;/span&gt;, slot, mSlots[slot].mBufferState);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; BAD_VALUE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//将slot的mRequestBufferCalled 标志位置为true，并返回指定index的slot的Graphicbuffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSlots[slot].mRequestBufferCalled = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    *buf = mSlots[slot].mGraphicBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个比较简单，还是很好理解的额，就是根据指定index取出mSlots中的slot中的buffer。&lt;/p&gt;
&lt;h2 id=&quot;匿名共享内存-OR-帧缓冲区&quot;&gt;&lt;a href=&quot;#匿名共享内存-OR-帧缓冲区&quot; class=&quot;headerlink&quot; title=&quot;匿名共享内存 OR 帧缓冲区&quot;&gt;&lt;/a&gt;匿名共享内存 OR 帧缓冲区&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们上边在注释中说了，申请的图形缓冲区是在匿名共享内存中申请的，不是直接在帧缓冲区。这个是有原因，我们下面分析一下。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;之前在&lt;a href=&quot;http://windrunnerlihuan.com/2017/03/12/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B8%80-Android%E5%9B%BE%E5%BD%A2%E6%98%BE%E7%A4%BA%E4%B9%8BHAL%E5%B1%82Gralloc%E6%A8%A1%E5%9D%97%E5%AE%9E%E7%8E%B0/&quot;&gt;Android SurfaceFlinger 学习之路(一)—-Android图形显示之HAL层Gralloc模块实现&lt;/a&gt;中我们讲过：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;图形缓冲区可以从系统帧缓冲区分配也可以从内存中分配，分配一个图形缓冲区后还需要将该图形缓冲区映射到分配该buffer的进程地址空间来，在Android系统中，图形缓冲区的管理由SurfaceFlinger服务来负责。在系统帧缓冲区中分配的图形缓冲区是在SurfaceFlinger服务中使用，而在内存中分配的图形缓冲区既可以在SurfaceFlinger服务中使用，也可以在其它的应用程序中使用。当其它的应用程序需要使用图形缓冲区的时候，它们就会请求SurfaceFlinger服务为它们分配并将SurfaceFlinger服务返回来的图形缓冲区映射到应用程序进程地址空间。在从内存中分配buffer时，已经将分配的buffer映射到了SurfaceFlinger服务进程地址空间，如果该buffer是应用程序请求SurfaceFlinger服务为它们分配的，那么还需要将SurfaceFlinger服务返回来的图形缓冲区映射到应用程序进程地址空间。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们这里是应用请求SurfaceFlinger去分配图形缓冲，在匿名共享内存当中。我们要去验证一下。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;首先在&lt;a href=&quot;http://windrunnerlihuan.com/2017/03/12/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B8%80-Android%E5%9B%BE%E5%BD%A2%E6%98%BE%E7%A4%BA%E4%B9%8BHAL%E5%B1%82Gralloc%E6%A8%A1%E5%9D%97%E5%AE%9E%E7%8E%B0/&quot;&gt;Android SurfaceFlinger 学习之路(一)—-Android图形显示之HAL层Gralloc模块实现&lt;/a&gt;中讲到，用户空间的应用程序用到的图形缓冲区是由Gralloc模块中的函数gralloc_alloc来分配的，这个函数实现在文件hardware/libhardware/modules/gralloc/gralloc.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;gralloc_alloc&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;alloc_device_t&lt;/span&gt;* dev,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; h, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; format, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; usage,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt;* pHandle, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;* pStride)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!pHandle || !pStride)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -EINVAL;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; size, stride;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; align = &lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; bpp = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt; (format) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HAL_PIXEL_FORMAT_RGBA_8888:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HAL_PIXEL_FORMAT_RGBX_8888:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HAL_PIXEL_FORMAT_BGRA_8888:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            bpp = &lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HAL_PIXEL_FORMAT_RGB_888:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            bpp = &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HAL_PIXEL_FORMAT_RGB_565:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HAL_PIXEL_FORMAT_RAW_SENSOR:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            bpp = &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;default&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -EINVAL;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; bpr = (w*bpp + (align&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;)) &amp;amp; ~(align&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    size = bpr * h;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    stride = bpr / bpp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (usage &amp;amp; GRALLOC_USAGE_HW_FB) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        err = gralloc_alloc_framebuffer(dev, size, usage, pHandle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        err = gralloc_alloc_buffer(dev, size, usage, pHandle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    *pStride = stride;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;参数usage用来描述要分配的图形缓冲区的用途。如果是用来在系统帧缓冲区中渲染的，即参数usage的&lt;strong&gt;GRALLOC_USAGE_HW_FB&lt;/strong&gt;位等于1，那么就必须要系统帧缓冲区中分配，否则的话，就在内存中分配。注意，在内存中分配的图形缓冲区，最终是需要拷贝到系统帧缓冲区去的，以便可以将它所描述的图形渲染出来。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;而这个usage是由上层app然后到SurfaceFlinger一系列过程增减标志位的，所以我们从下往上，看看标志是怎么设置的。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;同事我们回顾&lt;a href=&quot;http://windrunnerlihuan.com/2017/06/22/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B8%83-%E5%88%9B%E5%BB%BA%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BAGraphicBuffer/&quot;&gt;Android SurfaceFlinger 学习之路(七)—-创建图形缓冲区GraphicBuffer&lt;/a&gt;的内容。标志位设置在一下几个地方：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）创建Layer时候，在onFirstRef函数中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; Layer::onFirstRef() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//这里getEffectiveUsage获取一些标志位&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer-&amp;gt;setConsumerUsageBits(getEffectiveUsage(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里getEffectiveUsage获取一些标志位，我们继续查看：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; Layer::getEffectiveUsage(&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; usage) &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;TODO:&lt;/span&gt; should we do something special if mSecure is set?&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mProtectedByApp) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//// application requires protected path to external sink&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// need a hardware-protected path to external video sink&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        usage |= GraphicBuffer::USAGE_PROTECTED;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mPotentialCursor) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//// This layer can be a cursor on some displays.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        usage |= GraphicBuffer::USAGE_CURSOR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    usage |= GraphicBuffer::USAGE_HW_COMPOSER;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; usage;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果mProtectedByApp为true，则设置GraphicBuffer::USAGE_PROTECTED标志位，默认为false；如果mPotentialCursor为true，设置USAGE_CURSOR标志位，默认为false。这两个注释已经说明了。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;最后设置GraphicBuffer::USAGE_HW_COMPOSER，表示使用HWC硬件合成。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）在上面Surface的lock方法中，设置了setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);we’re intending to do software rendering from this point，打算使用软件绘制。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）Surface的lock方法中，锁定图形缓冲区的函数调用处：status_t res = backBuffer-&amp;gt;lockAsync(&lt;br&gt;                GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,&lt;br&gt;                newDirtyRegion.bounds(), &amp;amp;vaddr, fenceFd);函数就会将参数usage的值修改为(GraphicBuffer::USAGE_SW_READ_OFTEN | GraphicBuffer::USAGE_SW_WRITE_OFTEN)，目的是防止该Surface的图形缓冲区直接在硬件帧缓冲区上分配。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）上层app在WindowStateAnimator的createSurfaceLocked构建java层SurfaceControl时也仅仅设置了几个变量：&lt;br&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;SurfaceControl &lt;span class=&quot;title&quot;&gt;createSurfaceLocked&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; flags = SurfaceControl.HIDDEN;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt; WindowManager.LayoutParams attrs = w.mAttrs;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((attrs.flags&amp;amp;WindowManager.LayoutParams.FLAG_SECURE) != &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                flags |= SurfaceControl.SECURE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mService.isScreenCaptureDisabledLocked(UserHandle.getUserId(mWin.mOwnerUid))) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                flags |= SurfaceControl.SECURE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!PixelFormat.formatHasAlpha(attrs.format)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;amp;&amp;amp; attrs.surfaceInsets.left == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;amp;&amp;amp; attrs.surfaceInsets.top == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;amp;&amp;amp; attrs.surfaceInsets.right == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;amp;&amp;amp; attrs.surfaceInsets.bottom  == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    flags |= SurfaceControl.OPAQUE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSurfaceControl = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; SurfaceControl(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mSession.mSurfaceSession,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                attrs.getTitle().toString(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                width, height, format, flags);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;也是简单的flag，影响不大。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们找了这么多，也没有&lt;strong&gt;GRALLOC_USAGE_HW_FB&lt;/strong&gt;标志位。我们再看看这些标志位的定义，位于hardware/libhardware/include/hardware/Gralloc.h：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;enum&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* buffer is never read in software */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_SW_READ_NEVER         = &lt;span class=&quot;number&quot;&gt;0x00000000&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* buffer is rarely read in software */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_SW_READ_RARELY        = &lt;span class=&quot;number&quot;&gt;0x00000002&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* buffer is often read in software */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_SW_READ_OFTEN         = &lt;span class=&quot;number&quot;&gt;0x00000003&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* mask for the software read values */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_SW_READ_MASK          = &lt;span class=&quot;number&quot;&gt;0x0000000F&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* buffer is never written in software */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_SW_WRITE_NEVER        = &lt;span class=&quot;number&quot;&gt;0x00000000&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* buffer is rarely written in software */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_SW_WRITE_RARELY       = &lt;span class=&quot;number&quot;&gt;0x00000020&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* buffer is often written in software */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_SW_WRITE_OFTEN        = &lt;span class=&quot;number&quot;&gt;0x00000030&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* mask for the software write values */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_SW_WRITE_MASK         = &lt;span class=&quot;number&quot;&gt;0x000000F0&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* buffer will be used as an OpenGL ES texture */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_HW_TEXTURE            = &lt;span class=&quot;number&quot;&gt;0x00000100&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* buffer will be used as an OpenGL ES render target */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_HW_RENDER             = &lt;span class=&quot;number&quot;&gt;0x00000200&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* buffer will be used by the 2D hardware blitter */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_HW_2D                 = &lt;span class=&quot;number&quot;&gt;0x00000400&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* buffer will be used by the HWComposer HAL module */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_HW_COMPOSER           = &lt;span class=&quot;number&quot;&gt;0x00000800&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* buffer will be used with the framebuffer device */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_HW_FB                 = &lt;span class=&quot;number&quot;&gt;0x00001000&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* buffer will be used with the HW video encoder */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_HW_VIDEO_ENCODER      = &lt;span class=&quot;number&quot;&gt;0x00010000&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* buffer will be written by the HW camera pipeline */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_HW_CAMERA_WRITE       = &lt;span class=&quot;number&quot;&gt;0x00020000&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* buffer will be read by the HW camera pipeline */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_HW_CAMERA_READ        = &lt;span class=&quot;number&quot;&gt;0x00040000&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* buffer will be used as part of zero-shutter-lag queue */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_HW_CAMERA_ZSL         = &lt;span class=&quot;number&quot;&gt;0x00060000&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* mask for the camera access values */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_HW_CAMERA_MASK        = &lt;span class=&quot;number&quot;&gt;0x00060000&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* mask for the software usage bit-mask */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_HW_MASK               = &lt;span class=&quot;number&quot;&gt;0x00071F00&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* buffer will be used as a RenderScript Allocation */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_RENDERSCRIPT          = &lt;span class=&quot;number&quot;&gt;0x00100000&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* buffer should be displayed full-screen on an external display when&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * possible&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_EXTERNAL_DISP         = &lt;span class=&quot;number&quot;&gt;0x00002000&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* Must have a hardware-protected path to external display sink for&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * this buffer.  If a hardware-protected path is not available, then&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * either don&#39;t composite only this buffer (preferred) to the&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * external sink, or (less desirable) do not route the entire&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * composition to the external sink.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_PROTECTED             = &lt;span class=&quot;number&quot;&gt;0x00004000&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* buffer may be used as a cursor */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_CURSOR                = &lt;span class=&quot;number&quot;&gt;0x00008000&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* implementation-specific private usage flags */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_PRIVATE_0             = &lt;span class=&quot;number&quot;&gt;0x10000000&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_PRIVATE_1             = &lt;span class=&quot;number&quot;&gt;0x20000000&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_PRIVATE_2             = &lt;span class=&quot;number&quot;&gt;0x40000000&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_PRIVATE_3             = &lt;span class=&quot;number&quot;&gt;0x80000000&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GRALLOC_USAGE_PRIVATE_MASK          = &lt;span class=&quot;number&quot;&gt;0xF0000000&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;由于整个系统在硬件上就只有一个帧缓冲区，它是由SurfaceFlinger服务来统一管理的，即只有SurfaceFlinger服务使用的图形缓冲区才可以在上面分配，否则的话，随便一个应用程序进程都可以在上面分配图形缓冲区来使用，这个帧缓冲区的管理就乱套了。应用程序进程使用的图形缓冲区一般都是在匿名共享内存里面分配的，这个图形缓冲区填好数据之后，就会再交给SurfaceFlinger服务来合成到硬件帧缓冲区上去渲染。因此，从前面传过来给函数gralloc_alloc的参数usage的GRALLOC_USAGE_HW_FB位会被设置为0，以便可以在匿名共享内存中分配一个图形缓冲区。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;图形缓冲区入队&quot;&gt;&lt;a href=&quot;#图形缓冲区入队&quot; class=&quot;headerlink&quot; title=&quot;图形缓冲区入队&quot;&gt;&lt;/a&gt;图形缓冲区入队&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们前面讲了，省略了第二步绘制流程，因此我们这里分析第三部，绘制完毕后再queueBuffer。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;同样，调用了Surface的unlockCanvasAndPost函数，我们查看它的实现：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; Surface::unlockAndPost()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mLockedBuffer == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;Surface::unlockAndPost failed, no locked buffer&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; INVALID_OPERATION;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; fd = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//解锁图形缓冲区，和前面的lockAsync成对出现&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = mLockedBuffer-&amp;gt;unlockAsync(&amp;amp;fd);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGE_IF(err, &lt;span class=&quot;string&quot;&gt;&quot;failed unlocking buffer (%p)&quot;&lt;/span&gt;, mLockedBuffer-&amp;gt;handle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//queueBuffer去归还图形缓冲区&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    err = queueBuffer(mLockedBuffer.get(), fd);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGE_IF(err, &lt;span class=&quot;string&quot;&gt;&quot;queueBuffer (handle=%p) failed (%s)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mLockedBuffer-&amp;gt;handle, strerror(-err));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//将绘制buffer赋值给mPostedBuffer ，在lock函数里提到了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mPostedBuffer = mLockedBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//最后将mLockedBuffer 置为0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mLockedBuffer = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里也比较简单，核心也是分两步：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）解锁图形缓冲区，和前面的lockAsync成对出现；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）queueBuffer去归还图形缓冲区；&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以我们还是重点分析第二步，查看queueBuffer的实现：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; Surface::queueBuffer(&lt;span class=&quot;keyword&quot;&gt;android_native_buffer_t&lt;/span&gt;* buffer, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; fenceFd) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGV(&lt;span class=&quot;string&quot;&gt;&quot;Surface::queueBuffer&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int64_t&lt;/span&gt; timestamp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; isAutoTimestamp = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        timestamp = systemTime(SYSTEM_TIME_MONOTONIC);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        isAutoTimestamp = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGV(&lt;span class=&quot;string&quot;&gt;&quot;Surface::queueBuffer making up timestamp: %.2f ms&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            timestamp / &lt;span class=&quot;number&quot;&gt;1000000.f&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        timestamp = mTimestamp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//获取图形缓冲区的slot在mSlots中的index&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; i = getSlotFromBufferLocked(buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (i &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; i;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Make sure the crop rectangle is entirely inside the buffer.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    确保剪裁的区域完全位于图形缓冲区内部&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Rect crop;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCrop.intersect(Rect(buffer-&amp;gt;width, buffer-&amp;gt;height), &amp;amp;crop);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;Fence&amp;gt; fence(fenceFd &amp;gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ? &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Fence(fenceFd) : Fence::NO_FENCE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//创建in、out两个栈对象，用于填充数据&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    IGraphicBufferProducer::QueueBufferOutput output;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    IGraphicBufferProducer::&lt;span class=&quot;function&quot;&gt;QueueBufferInput &lt;span class=&quot;title&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(timestamp, isAutoTimestamp,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            crop, mScalingMode, mTransform ^ mStickyTransform, mSwapIntervalZero,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            fence, mStickyTransform)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//调用BufferQueueProducer的queueBuffer归还缓冲区&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = mGraphicBufferProducer-&amp;gt;queueBuffer(i, input, &amp;amp;output);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != OK)  &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;queueBuffer: error queuing buffer to SurfaceTexture, %d&quot;&lt;/span&gt;, err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; numPendingBuffers = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; hint = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//解析赋值给全局变量&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    output.deflate(&amp;amp;mDefaultWidth, &amp;amp;mDefaultHeight, &amp;amp;hint,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;amp;numPendingBuffers);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Disable transform hint if sticky transform is set.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mStickyTransform == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mTransformHint = hint;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mConsumerRunningBehind = (numPendingBuffers &amp;gt;= &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里创建了QueueBufferOutput、QueueBufferInput 两个栈对象用来传输数据，这两个我们在下面的附件内容会讲到，有一些关于结构体的知识。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上述的核心就是调用BufferQueueProducer的queueBuffer归还缓冲区，j将绘制后的图形缓冲区queue回去。我们依然省略IPC Binder过程，直接看实现：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;96&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;97&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;98&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;99&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;100&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;101&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;102&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;103&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;104&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;105&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;106&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;107&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;108&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;109&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;110&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;status_t BufferQueueProducer::queueBuffer(int slot,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const QueueBufferInput &amp;amp;input, QueueBufferOutput *output) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_BUFFER_INDEX(slot);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    int64_t timestamp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    bool isAutoTimestamp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Rect crop;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    int scalingMode;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    uint32_t transform;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    uint32_t stickyTransform;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    bool async;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;Fence&amp;gt; fence;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //从传入的QueueBufferInput ，解析填充一些变量&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    input.deflate(&amp;amp;timestamp, &amp;amp;isAutoTimestamp, &amp;amp;crop, &amp;amp;scalingMode, &amp;amp;transform,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;amp;async, &amp;amp;fence, &amp;amp;stickyTransform);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;IConsumerListener&amp;gt; listener;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123; // Autolock scope&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Mutex::Autolock lock(mCore-&amp;gt;mMutex);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ...省略一些错误判断逻辑...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //获取入队的GraphicBuffer的区域大小&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const sp&amp;lt;GraphicBuffer&amp;gt;&amp;amp; graphicBuffer(mSlots[slot].mGraphicBuffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Rect bufferRect(graphicBuffer-&amp;gt;getWidth(), graphicBuffer-&amp;gt;getHeight());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Rect croppedRect;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        crop.intersect(bufferRect, &amp;amp;croppedRect);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (croppedRect != crop) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            BQ_LOGE(&quot;queueBuffer: crop rect is not contained within the &quot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &quot;buffer in slot %d&quot;, slot);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            return BAD_VALUE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //改变入队的slot的状态为QUEUED&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSlots[slot].mFence = fence;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSlots[slot].mBufferState = BufferSlot::QUEUED;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //每次推进来，mFrameCounter都加1，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //上一篇讲分配缓冲区返回最老的FREE状态buffer，就是用这个mFrameCounter最小值判断&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ++mCore-&amp;gt;mFrameCounter;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSlots[slot].mFrameNumber = mCore-&amp;gt;mFrameCounter;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //创建一个BufferItem来描述GraphicBuffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        BufferItem item;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        item.mAcquireCalled = mSlots[slot].mAcquireCalled;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        item.mCrop = crop;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        item.mTransform = transform &amp;amp; ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        item.mTransformToDisplayInverse =&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                bool(transform &amp;amp; NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        item.mScalingMode = scalingMode;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        item.mTimestamp = timestamp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        item.mIsAutoTimestamp = isAutoTimestamp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        item.mFrameNumber = mCore-&amp;gt;mFrameCounter;//每次加1，最小的肯定是最早推进去的&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        item.mSlot = slot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        item.mFence = fence;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        item.mIsDroppable = mCore-&amp;gt;mDequeueBufferCannotBlock || async;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mStickyTransform = stickyTransform;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (mCore-&amp;gt;mQueue.empty()) &amp;#123;//如果mQueue队列为空，则直接push进入这个mQueue，不用考虑阻塞&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // When the queue is empty, we can ignore mDequeueBufferCannotBlock&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // and simply queue this buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mCore-&amp;gt;mQueue.push_back(item);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            listener = mCore-&amp;gt;mConsumerListener;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; else &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // When the queue is not empty, we need to look at the front buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // state to see if we need to replace it&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //如果这个mQueue队列不为空，我们要看看它的队头的状态，然后判断是否替换它&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            BufferQueueCore::Fifo::iterator front(mCore-&amp;gt;mQueue.begin());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (front-&amp;gt;mIsDroppable) &amp;#123;//如果队头可以丢弃&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // If the front queued buffer is still being tracked, we first&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // mark it as freed&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //如果已经出队的buffer对应的slot依然保留在mSlots数组中，就要释放他，变为FREE状态&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                if (mCore-&amp;gt;stillTracking(front)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    mSlots[front-&amp;gt;mSlot].mBufferState = BufferSlot::FREE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    // Reset the frame number of the freed buffer so that it is&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    // the first in line to be dequeued again&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    mSlots[front-&amp;gt;mSlot].mFrameNumber = 0;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // Overwrite the droppable buffer with the incoming one&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //然后队头插入新入队的BufferItem&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                *front = item;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; else &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //如果队头不能丢弃，则直接将新的Item入队&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mCore-&amp;gt;mQueue.push_back(item);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //将BufferQueueCore的mConsumerListener赋给listener，这个我们上一节讲过&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                listener = mCore-&amp;gt;mConsumerListener;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mCore-&amp;gt;mBufferHasBeenQueued = true;//入队后mBufferHasBeenQueued 置为true&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //上一篇讲了，没有空闲buffer去dequeue，则要等待，这里解除等待&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mCore-&amp;gt;mDequeueCondition.broadcast();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        output-&amp;gt;inflate(mCore-&amp;gt;mDefaultWidth, mCore-&amp;gt;mDefaultHeight,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mCore-&amp;gt;mTransformHint, mCore-&amp;gt;mQueue.size());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ATRACE_INT(mCore-&amp;gt;mConsumerName.string(), mCore-&amp;gt;mQueue.size());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; // Autolock scope&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // Call back without lock held&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //然后通知SurfaceFlinger去消费，这个我们上一篇讲过，下面会在分析&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (listener != NULL) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        listener-&amp;gt;onFrameAvailable();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    return NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;queueBuffer方法也挺长的，但是我们分部查看，每一步也不难：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）从传入的QueueBufferInput ，解析填充一些变量；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）改变入队Slot的状态为QUEUED，每次推进来，mFrameCounter都加1。这里的slot，上一篇讲分配缓冲区返回最老的FREE状态buffer，就是用这个mFrameCounter最小值判断，就是上一篇LRU算法的判断；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）创建一个BufferItem来描述GraphicBuffer，用mSlots[slot]中的slot填充BufferItem；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）将BufferItem塞进mCore的mQueue队列，依照指定规则；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;5）然后通知SurfaceFlinger去消费，这个我们上一篇讲过，这个我们下面会讲到。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上述lockCanvas和unlockCanvasAndPost可以用下图来总结一下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%85%AB%29----Surface%E7%AE%A1%E7%90%86%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BA/lockunlock.jpg&quot; alt=&quot;lockunlock&quot;&gt;&lt;/p&gt;
&lt;h1 id=&quot;通知SF消费合成&quot;&gt;&lt;a href=&quot;#通知SF消费合成&quot; class=&quot;headerlink&quot; title=&quot;通知SF消费合成&quot;&gt;&lt;/a&gt;通知SF消费合成&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面讲到，当绘制完毕的GraphicBuffer入队之后，会通知SurfaceFlinger去消费，就是BufferQueueProducer的queueBuffer函数的最后几行，listener-&amp;gt;onFrameAvailable()。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个listener赋值为mCore-&amp;gt;mConsumerListener，我们上一篇&lt;a href=&quot;http://windrunnerlihuan.com/2017/06/22/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B8%83-%E5%88%9B%E5%BB%BA%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BAGraphicBuffer/&quot;&gt;Android SurfaceFlinger 学习之路(七)—-创建图形缓冲区GraphicBuffer&lt;/a&gt;在讲到Consumer时候，得知这个listener最终通过回调，会回到Layer当中，所以最终调用Layer的onFrameAvailable接口，我们看看它的实现：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; Layer::onFrameAvailable() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    android_atomic_inc(&amp;amp;mQueuedFrames);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFlinger-&amp;gt;signalLayerUpdate();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里又调用SurfaceFlinger的signalLayerUpdate函数，继续查看：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::signalLayerUpdate() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEventQueue.invalidate();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里又调用MessageQueue的invalidate函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; MessageQueue::invalidate() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; INVALIDATE_ON_VSYNC  &lt;span class=&quot;comment&quot;&gt;//1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEvents-&amp;gt;requestNextVsync();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;else&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mHandler-&amp;gt;dispatchInvalidate();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;到这里就比较熟悉了，就是们讲Vsync信号的时候内容了，可以查看&lt;a href=&quot;http://windrunnerlihuan.com/2017/05/25/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%BA%94-VSync-%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/&quot;&gt;Android SurfaceFlinger 学习之路(五)—-VSync 工作原理&lt;/a&gt;。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;其实上面和下面执行的逻辑都一样，最种结果都会走到SurfaceFlinger的vsync信号接收逻辑，即SurfaceFlinger的onMessageReceived函数，走的case是INVALIDATE：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::onMessageReceived(&lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; what) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt; (what) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; MessageQueue::TRANSACTION:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        handleMessageTransaction();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; MessageQueue::INVALIDATE:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        handleMessageTransaction();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        handleMessageInvalidate();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        signalRefresh();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; MessageQueue::REFRESH:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        handleMessageRefresh();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceFlinger就去消费这块图形缓冲，然后合成图像，送给FrameBuffer，显示设备读取FrameBuffer内容去显示。这个我们以后再讲。&lt;/p&gt;
&lt;h1 id=&quot;附：结构体对齐&quot;&gt;&lt;a href=&quot;#附：结构体对齐&quot; class=&quot;headerlink&quot; title=&quot;附：结构体对齐&quot;&gt;&lt;/a&gt;附：结构体对齐&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们上面讲Surface的queueBuffer时候，会创建QueueBufferOutput、QueueBufferInput 两个栈对象用来传输数据。他们定义位于frameworks/native/include/gui/IGraphicBufferProducer.h：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;struct QueueBufferInput : public Flattenable&amp;lt;QueueBufferInput&amp;gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    friend class Flattenable&amp;lt;QueueBufferInput&amp;gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    inline QueueBufferInput(const Parcel&amp;amp; parcel);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // timestamp - a monotonically increasing value in nanoseconds&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // isAutoTimestamp - if the timestamp was synthesized at queue time&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // crop - a crop rectangle that&#39;s used as a hint to the consumer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // scalingMode - a set of flags from NATIVE_WINDOW_SCALING_* in &amp;lt;window.h&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // transform - a set of flags from NATIVE_WINDOW_TRANSFORM_* in &amp;lt;window.h&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // async - if the buffer is queued in asynchronous mode&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // fence - a fence that the consumer must wait on before reading the buffer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //         set this to Fence::NO_FENCE if the buffer is ready immediately&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // sticky - the sticky transform set in Surface (only used by the LEGACY&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //          camera mode).&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    inline QueueBufferInput(int64_t timestamp, bool isAutoTimestamp,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const Rect&amp;amp; crop, int scalingMode, uint32_t transform, bool async,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            const sp&amp;lt;Fence&amp;gt;&amp;amp; fence, uint32_t sticky = 0)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    : timestamp(timestamp), isAutoTimestamp(isAutoTimestamp), crop(crop),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      scalingMode(scalingMode), transform(transform), stickyTransform(sticky),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      async(async), fence(fence) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    inline void deflate(int64_t* outTimestamp, bool* outIsAutoTimestamp,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Rect* outCrop, int* outScalingMode, uint32_t* outTransform,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            bool* outAsync, sp&amp;lt;Fence&amp;gt;* outFence,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            uint32_t* outStickyTransform = NULL) const &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        *outTimestamp = timestamp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        *outIsAutoTimestamp = bool(isAutoTimestamp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        *outCrop = crop;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        *outScalingMode = scalingMode;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        *outTransform = transform;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        *outAsync = bool(async);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        *outFence = fence;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (outStickyTransform != NULL) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            *outStickyTransform = stickyTransform;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // Flattenable protocol&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    size_t getFlattenedSize() const;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    size_t getFdCount() const;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    status_t flatten(void*&amp;amp; buffer, size_t&amp;amp; size, int*&amp;amp; fds, size_t&amp;amp; count) const;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    status_t unflatten(void const*&amp;amp; buffer, size_t&amp;amp; size, int const*&amp;amp; fds, size_t&amp;amp; count);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;private:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    int64_t timestamp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    int isAutoTimestamp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Rect crop;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    int scalingMode;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    uint32_t transform;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    uint32_t stickyTransform;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    int async;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;Fence&amp;gt; fence;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;// QueueBufferOutput must be a POD structure&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;struct __attribute__ ((__packed__)) QueueBufferOutput &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    inline QueueBufferOutput() &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // outWidth - filled with default width applied to the buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // outHeight - filled with default height applied to the buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // outTransformHint - filled with default transform applied to the buffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // outNumPendingBuffers - num buffers queued that haven&#39;t yet been acquired&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //                        (counting the currently queued buffer)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    inline void deflate(uint32_t* outWidth,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            uint32_t* outHeight,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            uint32_t* outTransformHint,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            uint32_t* outNumPendingBuffers) const &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        *outWidth = width;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        *outHeight = height;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        *outTransformHint = transformHint;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        *outNumPendingBuffers = numPendingBuffers;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    inline void inflate(uint32_t inWidth, uint32_t inHeight,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            uint32_t inTransformHint, uint32_t inNumPendingBuffers) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        width = inWidth;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        height = inHeight;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        transformHint = inTransformHint;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        numPendingBuffers = inNumPendingBuffers;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;private:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    uint32_t width;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    uint32_t height;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    uint32_t transformHint;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    uint32_t numPendingBuffers;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这两个结构体，一个用来填充数据，一个用来解析数据。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们先看看结构字节对齐。&lt;/p&gt;
&lt;h2 id=&quot;结构体字节对齐&quot;&gt;&lt;a href=&quot;#结构体字节对齐&quot; class=&quot;headerlink&quot; title=&quot;结构体字节对齐&quot;&gt;&lt;/a&gt;结构体字节对齐&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在用sizeof运算符求算某结构体所占空间时，并不是简单地将结构体中所有元素各自占的空间相加，这里涉及到内存字节对齐的问题。从理论上讲，对于任何 变量的访问都可以从任何地址开始访问，但是事实上不是如此，实际上访问特定类型的变量只能在特定的地址访问，这就需要各个变量在空间上按一定的规则排列， 而不是简单地顺序排列，这就是内存对齐。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;内存对齐的原因：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;某些平台只能在特定的地址处访问特定类型的数据；&lt;/li&gt;
&lt;li&gt;提高存取数据的速度。比如有的平台每次都是从偶地址处读取数据，对于一个int型的变量，若从偶地址单元处存放，则只需一个读取周期即可读取该变量；但是若从奇地址单元处存放，则需要2个读取周期读取该变量。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;对齐策略：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;结构体变量的首地址能够被其最宽数据类型成员的大小整除。编译器在为结构体变量开辟空间时，首先找到结构体中最宽的数据类型，然后寻找内存地址能被该数据类型大小整除的位置，这个位置作为结构体变量的首地址。而将最宽数据类型的大小作为对齐标准。&lt;/li&gt;
&lt;li&gt;结构体每个成员相对结构体首地址的偏移量(offset)都是每个成员本身大小的整数倍，如有需要会在成员之间填充字节。编译器在为结构体成员开辟空 间时，首先检查预开辟空间的地址相对于结构体首地址的偏移量是否为该成员大小的整数倍，若是，则存放该成员；若不是，则填充若干字节，以达到整数倍的要求。&lt;/li&gt;
&lt;li&gt;结构体变量所占空间的大小必定是最宽数据类型大小的整数倍。如有需要会在最后一个成员末尾填充若干字节使得所占空间大小是最宽数据类型大小的整数倍。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;下面看一下sizeof在计算结构体大小的时候具体是怎样计算的：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）test1   空结构体&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; node&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;S;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;则sizeof(S)=1;或sizeof(S)=0;&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在C++中占1字节，而在C中占0字节。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）test2&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; node1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; a;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; b;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;short&lt;/span&gt; c;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;S1;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;则sizeof(S1)=8。这是因为结构体node1中最长的数据类型是int，占4个字节，因此以4字节对齐，则该结构体在内存中存放方式为:&lt;br&gt;&lt;code&gt;|--------int--------|   4字节&lt;/code&gt;&lt;br&gt;&lt;code&gt;|char|----|--short--|   4字节&lt;/code&gt;&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;总共占8字节&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）test3&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; node2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; a;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; b;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;short&lt;/span&gt; c;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;S2;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;则siezof(S3)=12.最长数据类型为int，占4个字节。因此以4字节对齐，其在内存空间存放方式如下:&lt;br&gt;&lt;code&gt;|char|----|----|----|  4字节&lt;/code&gt;&lt;br&gt;&lt;code&gt;|--------int--------|  4字节&lt;/code&gt;&lt;br&gt;&lt;code&gt;|--short--|----|----|  4字节&lt;/code&gt;&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;总共占12个字节&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）test4  含有静态数据成员&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; node3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; a;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;short&lt;/span&gt; b;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; c;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;S3;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;则sizeof(S3)=8。这里结构体中包含静态数据成员，而静态数据成员的存放位置与结构体实例的存储地址无关(注意只有在C++中结构体中才能含有静态数据成员，而C中结构体中是不允许含有静态数据成员的)。其在内存中存储方式如下：&lt;br&gt;&lt;code&gt;|--------int--------|   4字节&lt;/code&gt;&lt;br&gt;&lt;code&gt;|--short--|----|----|    4字节&lt;/code&gt;&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;而变量c是单独存放在静态数据区的，因此用siezof计算其大小时没有将c所占的空间计算进来。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;5）test5  结构体中含有结构体&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; node4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; a;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    S1 s1;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;short&lt;/span&gt; b;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;S4;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;数据成员包含另一个结构体变量s1的话，则取s1中最 长数据类型与其他数据成员比较，取最长的作为对齐标准，但是s1存放时看做一个单位存放，只需看其他成员即可。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;则sizeof(S4)=16。是因为s1占8字节，而s1中最长数据类型为int，占4个字节，bool类型1个字节，short占2字节，因此以4字节对齐，则存储方式为：&lt;br&gt;&lt;code&gt;|-------bool--------|  4字节&lt;/code&gt;&lt;br&gt;&lt;code&gt;|-------s1----------|  8字节&lt;/code&gt;&lt;br&gt;&lt;code&gt;|-------short-------|  4字节&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;6）test6&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; node5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; a;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    S1 s1;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;double&lt;/span&gt; b;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; c;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;S5;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;则sizeof(S5)=32。是因为s1占8字节，而s1中最长数据类型为int，占4字节，而double占8字节，因此以8字节对齐，则存放方式为：&lt;br&gt;&lt;code&gt;|--------bool--------|    8字节&lt;/code&gt;&lt;br&gt;&lt;code&gt;|---------s1---------|    8字节&lt;/code&gt;&lt;br&gt;&lt;code&gt;|--------double------|    8字节&lt;/code&gt;&lt;br&gt;&lt;code&gt;|----int----|--------|     8字节&lt;/code&gt; &lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;总结一下，在计算sizeof时主要注意一下几点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;若为空结构体，则只占1个字节的单元;&lt;/li&gt;
&lt;li&gt;若结构体中所有数据类型都相同，则其所占空间为 成员数据类型长度×成员个数；&lt;strong&gt;若结构体中数据类型不同，则取最长数据类型成员所占的空间为对齐标准，数据成员包含另一个结构体变量t的话，则取t中最 长数据类型与其他数据成员比较，取最长的作为对齐标准，但是t存放时看做一个单位存放，只需看其他成员即可&lt;/strong&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;attribute-关键字-双下划线相连并紧贴attribute&quot;&gt;&lt;a href=&quot;#attribute-关键字-双下划线相连并紧贴attribute&quot; class=&quot;headerlink&quot; title=&quot;  attribute   关键字(双下划线相连并紧贴attribute)&quot;&gt;&lt;/a&gt;&lt;em&gt; &lt;/em&gt; attribute &lt;em&gt; &lt;/em&gt; 关键字(双下划线相连并紧贴attribute)&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面的结构体对齐只是普通情况，但是如果对于指定了&lt;em&gt; &lt;/em&gt; attribute &lt;em&gt; &lt;/em&gt;(&lt;code&gt;由于MarkDown文本原因，打出来双下划线相连并紧贴attribute有问题，因此先这么表示&lt;/code&gt;)关键字，就不痛了。例如我们上面定义 QueueBufferOutput结构体也用了（&lt;em&gt; &lt;/em&gt; attribute &lt;em&gt; &lt;/em&gt; (( &lt;em&gt; &lt;/em&gt; packed &lt;em&gt; &lt;/em&gt;))）。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）&lt;em&gt; &lt;/em&gt; attribute &lt;em&gt; &lt;/em&gt;关键字主要是用来在函数或数据声明中设置其属性。给函数赋给属性的主要目的在于让编译器进行优化。函数声明中的&lt;em&gt; &lt;/em&gt; attribute &lt;em&gt; &lt;/em&gt;((noreturn))，就是告诉编译器这个函数不会返回给调用者，以便编译器在优化时去掉不必要的函数返回代码。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;GNU C的一大特色就是&lt;em&gt; &lt;/em&gt; attribute &lt;em&gt; &lt;/em&gt;机制。&lt;em&gt; &lt;/em&gt; attribute &lt;em&gt; &lt;/em&gt;可以设置函数属性（Function Attribute）、变量属性（Variable Attribute）和类型属性（Type Attribute）。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt; &lt;/em&gt; attribute &lt;em&gt; &lt;/em&gt;书写特征是：&lt;em&gt; &lt;/em&gt; attribute &lt;em&gt; &lt;/em&gt;前后都有两个下划线，并且后面会紧跟一对括弧，括弧里面是相应的&lt;em&gt; &lt;/em&gt; attribute &lt;em&gt; &lt;/em&gt;参数。 &lt;/li&gt;
&lt;li&gt;&lt;em&gt; &lt;/em&gt; attribute &lt;em&gt; &lt;/em&gt;语法格式为：&lt;em&gt; &lt;/em&gt; attribute &lt;em&gt; &lt;/em&gt; ((attribute-list))  其位置约束：放于声明的尾部“；”之前。&lt;/li&gt;
&lt;li&gt;函数属性（Function Attribute）：函数属性可以帮助开发者把一些特性添加到函数声明中，从而可以使编译器在错误检查方面的功能更强大。&lt;em&gt; &lt;/em&gt; attribute &lt;em&gt; &lt;/em&gt;机制也很容易同非GNU应用程序做到兼容之功效。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;GNU CC需要使用 –Wall编译器来击活该功能，这是控制警告信息的一个很好的方式。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2） &lt;em&gt; &lt;/em&gt; attribute &lt;em&gt; &lt;/em&gt; ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐，是GCC特有的语法。这个功能是跟操作系统没关系，跟编译器有关，gcc编译器不是紧凑模式的，我在windows下，用vc的编译器也不是紧凑的，用tc的编译器就是紧凑的。例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在TC下：struct my{ char ch; int a;} sizeof(int)=2;sizeof(my)=3;（紧凑模式）&lt;/li&gt;
&lt;li&gt;在GCC下：struct my{ char ch; int a;} sizeof(int)=4;sizeof(my)=8;（非紧凑模式）&lt;/li&gt;
&lt;li&gt;在GCC下：struct my{ char ch; int a;}&lt;em&gt; &lt;/em&gt; attrubte &lt;em&gt; &lt;/em&gt; ((packed)) sizeof(int)=4;sizeof(my)=5&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;packed属性：使用该属性可以使得变量或者结构体成员使用最小的对齐方式，即对变量是一字节对齐，对域（field）是位对齐。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）若使用了&lt;em&gt; &lt;/em&gt; attribute &lt;em&gt; &lt;/em&gt; ((aligned(n)))命令强制对齐标准，则取n和结构体中最长数据类型占的字节数两者之中的小者作为对齐标准。内存对齐，往往是由编译器来做的，如果你使用的是gcc，可以在定义变量时，添加&lt;em&gt; &lt;/em&gt; attribute &lt;em&gt; &lt;/em&gt;，来决定是否使用内存对齐，或是内存对齐到几个字节，以上面面的结构体为例：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; __attribute__ ((aligned(&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;))) node5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; a;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    S1 s1;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;double&lt;/span&gt; b;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; c;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;S5;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;则sizeof(S5)=24。因为强制以4字节对齐，而S5中最长数据类型为double，占8字节，因此以4字节对齐。在内存中存放方式为：&lt;br&gt;&lt;code&gt;|-----------a--------|   4字节&lt;/code&gt;&lt;br&gt;&lt;code&gt;|--------s1----------|   4字节&lt;/code&gt;&lt;br&gt;&lt;code&gt;|--------s1----------|   4字节&lt;/code&gt;&lt;br&gt;&lt;code&gt;|--------b-----------|   4字节&lt;/code&gt;&lt;br&gt;&lt;code&gt;|--------b-----------|   4字节&lt;/code&gt;&lt;br&gt;&lt;code&gt;|---------c----------|    4字节&lt;/code&gt;&lt;/p&gt;
&lt;h1 id=&quot;参考&quot;&gt;&lt;a href=&quot;#参考&quot; class=&quot;headerlink&quot; title=&quot;参考&quot;&gt;&lt;/a&gt;参考&lt;/h1&gt;&lt;p&gt;&lt;a href=&quot;http://www.unixwiz.net/techtips/gnu-c-attributes.html&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;http://www.unixwiz.net/techtips/gnu-c-attributes.html&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;http://www.cnblogs.com/dolphin0520/archive/2011/09/17/2179466.html&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;http://www.cnblogs.com/dolphin0520/archive/2011/09/17/2179466.html&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;小结&quot;&gt;&lt;a href=&quot;#小结&quot; class=&quot;headerlink&quot; title=&quot;小结&quot;&gt;&lt;/a&gt;小结&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;本篇我们讲了Surface对图形缓冲区的管理，前面从Activity到Surface创建过程我们只大概提了下，这个放在以后有空会分析的。下一篇我们讲讲SurfaceFlinger消费图形缓冲区，还有合成等等操作。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;唉，有一件特别悲催的事情，就是我失业了ToT，所以估计有一段时间不能更新了，望大家见谅。&lt;br&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%85%AB%29----Surface%E7%AE%A1%E7%90%86%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BA/meizi.jpg&quot; alt=&quot;meizi&quot;&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;本节我们学习一下上层app创建Surface到底层Surface管理图形缓冲区的简要过程，详细的从Activity到WMS最后至底层SurfaceFlinger消费surface我们以后再分析。&lt;br&gt;
    
    </summary>
    
      <category term="Android技术点" scheme="http://windrunnerlihuan.com/categories/Android%E6%8A%80%E6%9C%AF%E7%82%B9/"/>
    
    
      <category term="SurfaceFlinger" scheme="http://windrunnerlihuan.com/tags/SurfaceFlinger/"/>
    
  </entry>
  
  <entry>
    <title>Android SurfaceFlinger 学习之路(七)----创建图形缓冲区GraphicBuffer</title>
    <link href="http://windrunnerlihuan.com/2017/06/22/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B8%83-%E5%88%9B%E5%BB%BA%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BAGraphicBuffer/"/>
    <id>http://windrunnerlihuan.com/2017/06/22/Android-SurfaceFlinger-学习之路-七-创建图形缓冲区GraphicBuffer/</id>
    <published>2017-06-22T14:33:29.000Z</published>
    <updated>2019-01-06T07:27:44.793Z</updated>
    
    <content type="html">&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在上一篇SurfaceFlinger创建Surface流程中，我们会关联到BufferQueue对GraphicBuffer的管理机制，我们这次就来分析一下它的原理。&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;角色扮演&quot;&gt;&lt;a href=&quot;#角色扮演&quot; class=&quot;headerlink&quot; title=&quot;角色扮演&quot;&gt;&lt;/a&gt;角色扮演&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Android应用的UI显示到Display的过程中，SurfaceFlinger扮演的角色只是“Flinger”，就是定于检查Layer更新，然后计算DirtyRegion，然后将结果推送给底层显示驱动进行显示。但是在App端，Surface的内容绘制却由应用层来承担。应用层绘制UI内容都需要一个GraphicBuffer，那么Surface对GraphicBuffer的申请、绘制完毕交给SurfaceFlinger去合成然后显示，这个工作也需要一套机制去管理。所以对于GraphicBuffer的管理，Android也设计了一套机制：BufferQueue，作为SurfaceFlinger管理和消费surface的中介。&lt;/p&gt;
&lt;h2 id=&quot;生产-消费-模型&quot;&gt;&lt;a href=&quot;#生产-消费-模型&quot; class=&quot;headerlink&quot; title=&quot;生产-消费 模型&quot;&gt;&lt;/a&gt;生产-消费 模型&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;回顾&lt;a href=&quot;http://windrunnerlihuan.com/2017/04/27/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%BA%8C-SurfaceFlinger%E6%A6%82%E8%BF%B0/&quot;&gt;Android SurfaceFlinger 学习之路(二)—-SurfaceFlinger概述&lt;/a&gt;，我们可以用这副简图表示App、BufferQueue和SurfaceFlinger的关系。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/file/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%8C%29----SurfaceFlinger%E6%A6%82%E8%BF%B0/PC1.jpg&quot; alt=&quot;C/S&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;虽说是三者的关系，但是他们所属的层却只有两个，app属于Java层，BufferQueue/SurfaceFlinger属于native层。也就是说BufferQueue也是隶属SurfaceFlinger，所有工作围绕SurfaceFlinger展开。&lt;/p&gt;
&lt;h3 id=&quot;生产者模型&quot;&gt;&lt;a href=&quot;#生产者模型&quot; class=&quot;headerlink&quot; title=&quot;生产者模型&quot;&gt;&lt;/a&gt;生产者模型&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; 这里IGraphicBufferProducer就是app和BufferQueue重要桥梁，GraphicBufferProducer承担着单个应用进程中的UI显示需求，与BufferQueue打交道的就是它。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; 根据上一篇Surface的创建流程，我们从Surface类图分析了GraphicBufferProducer在Surface中的位置，下图也可以表示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/file/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%8C%29----SurfaceFlinger%E6%A6%82%E8%BF%B0/PC2.jpg&quot; alt=&quot;producer&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;BpGraphicBufferProducer是GraphicBufferProducer在客户端这边的代理对象，负责和SF交互，GraphicBufferProducer通过gbp（IGraphicBufferProducer类对象）向BufferQueue获取buffer，然后进行填充UI信息，当填充完毕会通知SF，SF知道后就对该Buffer进行下一步操作。&lt;strong&gt;典型的生产-消费者模式&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&quot;消费者模型&quot;&gt;&lt;a href=&quot;#消费者模型&quot; class=&quot;headerlink&quot; title=&quot;消费者模型&quot;&gt;&lt;/a&gt;消费者模型&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;BufferQueue和SurfaceFlinger之间的通信模式如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/file/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%8C%29----SurfaceFlinger%E6%A6%82%E8%BF%B0/consumer.jpg&quot; alt=&quot;consumer&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;也是有一对BpGraphicBufferConsumer/BnGraphicBufferConsumer支持他们之间的信息传输。&lt;/p&gt;
&lt;h1 id=&quot;模型实现&quot;&gt;&lt;a href=&quot;#模型实现&quot; class=&quot;headerlink&quot; title=&quot;模型实现&quot;&gt;&lt;/a&gt;模型实现&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上一篇创建Surface流程中，当创建Layer时候，在onFirstRef里面创建了一个生产者和消费者，并对两者进行了包装：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; Layer::onFirstRef() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Creates a custom BufferQueue for SurfaceFlingerConsumer to use&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;IGraphicBufferProducer&amp;gt; producer;&lt;span class=&quot;comment&quot;&gt;//生产者&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;IGraphicBufferConsumer&amp;gt; consumer;&lt;span class=&quot;comment&quot;&gt;//消费者&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BufferQueue::createBufferQueue(&amp;amp;producer, &amp;amp;consumer);&lt;span class=&quot;comment&quot;&gt;//创建生产者和消费者&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mProducer = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; MonitoredProducer(producer, mFlinger);&lt;span class=&quot;comment&quot;&gt;//包装生产者&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; SurfaceFlingerConsumer(consumer, mTextureName);&lt;span class=&quot;comment&quot;&gt;//包装消费者&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//设置消费者相关回调&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer-&amp;gt;setConsumerUsageBits(getEffectiveUsage(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer-&amp;gt;setContentsChangedListener(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer-&amp;gt;setName(mName);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;MonitoredProducer对象，这个对象只是一个代理，真正实是BufferQueueProducer类，这个对象和BufferQueueCore有关联，可以管理最多达64块的缓冲区。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceFlingerConsumer构造函数将BufferQueueConsumer传入，并设置相关回调，以便生产者填充完GraphicBuffer然后通知Consumer消费。&lt;/p&gt;
&lt;h2 id=&quot;Core&quot;&gt;&lt;a href=&quot;#Core&quot; class=&quot;headerlink&quot; title=&quot;Core&quot;&gt;&lt;/a&gt;Core&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以创建生产者和消费者就是由BufferQueue来创建，我们可以看看BufferQueue的createBufferQueue函数，位于frameworks/native/libs/gui/BufferQueue.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; BufferQueue::createBufferQueue(sp&amp;lt;IGraphicBufferProducer&amp;gt;* outProducer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;IGraphicBufferConsumer&amp;gt;* outConsumer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;IGraphicBufferAlloc&amp;gt;&amp;amp; allocator) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//allocator == NULL&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//创建一个BufferQueueCore，她是核心&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;BufferQueueCore&amp;gt; core(&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; BufferQueueCore(allocator));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//用BufferQueueCore创建生产者&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;IGraphicBufferProducer&amp;gt; producer(&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; BufferQueueProducer(core));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//用core创建消费者&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;IGraphicBufferConsumer&amp;gt; consumer(&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; BufferQueueConsumer(core));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//向外面传入指针赋值&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    *outProducer = producer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    *outConsumer = consumer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以核心都是这个BufferQueueCore，他是管理图形缓冲区的中枢。这里举一个SurfaceTexture的例子，来看看他们之间的关系：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%B8%83%29----%E5%88%9B%E5%BB%BA%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BAGraphicBuffer/BufferQueue.jpg&quot; alt=&quot;BufferQueue&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;可以认为BufferQueueCore是一个服务中心，生产者、消费者都要通过它来管理buffer。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;里面有一个重要的成员数组：BufferQueueDefs::SlotsType mSlots;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;这个BufferSlot中有一个成员变量：sp&amp;lt; GraphicBuffer &amp;gt;mGraphicBuffer;记录这个slot所涉及的缓冲区；&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;另一个变量BufferState mBufferState;用于跟踪这个缓冲区的状态。&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）在BufferQueueCore类中定义了一个64项的数据mSlots，framework/native/libs/gui/BufferQueueCore.h：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// mSlots is an array of buffer slots that must be mirrored on the producer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// side. This allows buffer ownership to be transferred between the producer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// and consumer without sending a GraphicBuffer over Binder. The entire&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// array is initialized to NULL at construction time, and buffers are&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// allocated for a slot when requestBuffer is called with that slot&#39;s index.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;BufferQueueDefs::SlotsType mSlots;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们看看这个mSlot定义所在的位置，位于frameworks/native/include/gui/BufferQueueDefs.h中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;namespace&lt;/span&gt; BufferQueueDefs &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// BufferQueue will keep track of at most this value of buffers.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Attempts at runtime to increase the number of buffers past this&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// will fail.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;enum&lt;/span&gt; &amp;#123; NUM_BUFFER_SLOTS = &lt;span class=&quot;number&quot;&gt;64&lt;/span&gt; &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; BufferSlot SlotsType[NUM_BUFFER_SLOTS];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;comment&quot;&gt;// namespace BufferQueueDefs&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;我们可以看到这是一个容量大小为64的数组，因此BufferQueueCore可以管理最多64块的GraphicBuffer&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们可以帖一幅图表示Slot的角色：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%B8%83%29----%E5%88%9B%E5%BB%BA%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BAGraphicBuffer/slot.jpg&quot; alt=&quot;slot&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）BufferSlot的定义位于frameworks/native/include/gui/BufferSlot.h中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; BufferSlot &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BufferSlot()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    : mEglDisplay(EGL_NO_DISPLAY),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mBufferState(BufferSlot::FREE),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mRequestBufferCalled(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mFrameNumber(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mEglFence(EGL_NO_SYNC_KHR),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mAcquireCalled(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mNeedsCleanupOnRelease(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mAttachedByConsumer(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// mGraphicBuffer points to the buffer allocated for this slot or is NULL&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// if no buffer has been allocated.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;GraphicBuffer&amp;gt; mGraphicBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// BufferState represents the different states in which a buffer slot&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// can be.  All slots are initially FREE.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;enum&lt;/span&gt; BufferState &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// FREE indicates that the buffer is available to be dequeued&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// by the producer.  The buffer may be in use by the consumer for&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// a finite time, so the buffer must not be modified until the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// associated fence is signaled.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// The slot is &quot;owned&quot; by BufferQueue.  It transitions to DEQUEUED&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// when dequeueBuffer is called.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        FREE = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// DEQUEUED indicates that the buffer has been dequeued by the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// producer, but has not yet been queued or canceled.  The&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// producer may modify the buffer&#39;s contents as soon as the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// associated ready fence is signaled.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// The slot is &quot;owned&quot; by the producer.  It can transition to&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// QUEUED (via queueBuffer) or back to FREE (via cancelBuffer).&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        DEQUEUED = &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// QUEUED indicates that the buffer has been filled by the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// producer and queued for use by the consumer.  The buffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// contents may continue to be modified for a finite time, so&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// the contents must not be accessed until the associated fence&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// is signaled.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// The slot is &quot;owned&quot; by BufferQueue.  It can transition to&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// ACQUIRED (via acquireBuffer) or to FREE (if another buffer is&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// queued in asynchronous mode).&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        QUEUED = &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// ACQUIRED indicates that the buffer has been acquired by the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// consumer.  As with QUEUED, the contents must not be accessed&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// by the consumer until the fence is signaled.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// The slot is &quot;owned&quot; by the consumer.  It transitions to FREE&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// when releaseBuffer is called.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ACQUIRED = &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// mBufferState is the current state of this buffer slot.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BufferState mBufferState;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;mGraphicBuffer代表一块图形缓冲区GraphicBuffer，用于应用绘制UI。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;mBufferState类型为BufferState ，BufferState 的定义也位于其中，代表图形缓冲区的几种状态：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;FREE：buffer当前可用，可以被生产者dequeued，此时owner是BufferQueueCore，当dequeuebuffer调用时，状态可以转为dequeued。&lt;/li&gt;
&lt;li&gt;DEQUEUED：buffer已经被dequeued，还没被queue或canceld，此时owner是producer。&lt;/li&gt;
&lt;li&gt;QUEUED：buffer已经被生产者填充，并被queued，此时的owner是bufferQueueCore。&lt;/li&gt;
&lt;li&gt;ACQUIRED：buffer已经被消费者获得，此时的owner是consumer。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;一般的buffer大致会经过&lt;strong&gt;FREE-&amp;gt;DEQUEUED-&amp;gt;QUEUED-&amp;gt;ACQUIRED-&amp;gt;FREE&lt;/strong&gt;这个流程，我们下面会讲到它。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）在BufferQueueCore创建时候，还会创建一个GraphicBufferAlloc，并将它赋值给BufferQueueCore的mAllocator成员变量。我们可以看看BufferQueueCore的构造函数，位于framework/native/libs/gui/BufferQueueCore.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;BufferQueueCore::BufferQueueCore(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;IGraphicBufferAlloc&amp;gt;&amp;amp; allocator) :&lt;span class=&quot;comment&quot;&gt;//allocator为NULL&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mAllocator(allocator),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mMutex(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mIsAbandoned(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mConsumerControlledByApp(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mConsumerName(getUniqueName()),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mConsumerListener(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mConsumerUsageBits(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mConnectedApi(NO_CONNECTED_API),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mConnectedProducerListener(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSlots(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mQueue(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mOverrideMaxBufferCount(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDequeueCondition(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mUseAsyncBuffer(&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDequeueBufferCannotBlock(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDefaultWidth(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDefaultHeight(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDefaultMaxBufferCount(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mMaxAcquiredBufferCount(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mBufferHasBeenQueued(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFrameCounter(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mTransformHint(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mIsAllocating(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mIsAllocatingCondition()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (allocator == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//NULL&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;ISurfaceComposer&amp;gt; composer(ComposerService::getComposerService());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//请求SurfaceFlinger创建GraphicBufferAlloc&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mAllocator = composer-&amp;gt;createGraphicBufferAlloc();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mAllocator == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            BQ_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;createGraphicBufferAlloc failed&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后回去请求SurfaceFlinger创建一个GraphicBufferAlloc，位于frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sp&amp;lt;IGraphicBufferAlloc&amp;gt; SurfaceFlinger::createGraphicBufferAlloc()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//创建一个GraphicBufferAlloc对象，并赋给强指针&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;GraphicBufferAlloc&amp;gt; gba(&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; GraphicBufferAlloc());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; gba;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;因为BufferQueueCore的mAllocator 类型为IGraphicBufferAlloc，继承于IInterface，所以又是跨进程调用创建。我们下面会分析到它的。&lt;/p&gt;
&lt;h2 id=&quot;Producer&quot;&gt;&lt;a href=&quot;#Producer&quot; class=&quot;headerlink&quot; title=&quot;Producer&quot;&gt;&lt;/a&gt;Producer&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;BufferQueueProducer是生产者的实现，需要实现IGraphicBufferProducer接口，相关方法如下：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * This class defines the Binder IPC interface for the producer side of&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * a queue of graphics buffers.  It&#39;s used to send graphics data from one&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * component to another.  For example, a class that decodes video for&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * playback might use this to provide frames.  This is typically done&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * indirectly, through Surface.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; *&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * The underlying mechanism is a BufferQueue, which implements&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * BnGraphicBufferProducer.  In normal operation, the producer calls&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * dequeueBuffer() to get an empty buffer, fills it with data, then&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * calls queueBuffer() to make it available to the consumer.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; *&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * This class was previously called ISurfaceTexture.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; IGraphicBufferProducer : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; IInterface&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; status_t &lt;span class=&quot;title&quot;&gt;requestBuffer&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; slot, sp&amp;lt;GraphicBuffer&amp;gt;* buf)&lt;/span&gt; &lt;/span&gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; status_t &lt;span class=&quot;title&quot;&gt;dequeueBuffer&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;* slot, sp&amp;lt;Fence&amp;gt;* fence, &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; async,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; h, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; format, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; usage)&lt;/span&gt; &lt;/span&gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; status_t &lt;span class=&quot;title&quot;&gt;queueBuffer&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; slot,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; QueueBufferInput&amp;amp; input, QueueBufferOutput* output)&lt;/span&gt; &lt;/span&gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;cancelBuffer&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; slot, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;Fence&amp;gt;&amp;amp; fence)&lt;/span&gt; &lt;/span&gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......      &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这几个函数的注释写的很清楚，但是限于篇幅，没有贴出来。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;BufferQueueProducer的dequeueBuffer函数用来向BufferQueueCore申请一个空闲的slot，这个slot可能已经有缓冲区，也可能没有，如果没有缓冲区，&lt;strong&gt;dequeueBuffer函数会分配一块新的缓冲区&lt;/strong&gt;。得到空闲的slot后，还需要调用requestBuffer函数来&lt;strong&gt;取出&lt;/strong&gt;一块缓冲区，&lt;strong&gt;也是从BufferQueueCore中的mSlots数组根据index获取这个位置的slot&lt;/strong&gt;。得到缓冲区，如果不需要了，可以使用cancelBuffer函数来释放这个slot。调用dequeueBuffer函数之后，缓冲区的拥有者是生产者，缓冲区处于DEQUEUED状态。一旦缓冲区复制数据完成，&lt;strong&gt;通过queueBuffer函数把缓冲区的控制权交还给BufferQueueCore&lt;/strong&gt;，这时候缓冲区将处于QUEUED状态。这些函数的使用之处我们下面会讲到。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;BufferQueueProducer类图结构如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%B8%83%29----%E5%88%9B%E5%BB%BA%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BAGraphicBuffer/Producer.jpg&quot; alt=&quot;Producer&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;Consumer&quot;&gt;&lt;a href=&quot;#Consumer&quot; class=&quot;headerlink&quot; title=&quot;Consumer&quot;&gt;&lt;/a&gt;Consumer&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;同样，BufferQueueConsumer是消费者的实现，需要实现IGraphicBufferConsumer接口，相关方法如下：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; IGraphicBufferConsumer : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; IInterface &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; status_t &lt;span class=&quot;title&quot;&gt;acquireBuffer&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(BufferItem* buffer, &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; presentWhen)&lt;/span&gt; &lt;/span&gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; status_t &lt;span class=&quot;title&quot;&gt;releaseBuffer&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; buf, &lt;span class=&quot;keyword&quot;&gt;uint64_t&lt;/span&gt; frameNumber,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            EGLDisplay display, EGLSyncKHR fence,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;Fence&amp;gt;&amp;amp; releaseFence)&lt;/span&gt; &lt;/span&gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......        &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;注释写的很清晰，但是限于篇幅。。。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;BufferQueueConsumer类是接口IGraphicBufferComsumer的实现，是一个回调接口，&lt;strong&gt;如果BufferQueue中有数据准备好了通知消费者取走数据&lt;/strong&gt;。取走数据的时候，需要调用acquireBuffer函数，将缓冲区状态变成ACQUIRED，使用完之后调用releaseBuffer函数可以吧缓冲区数据归还给BufferQueueCore，这样缓冲区就变成FREE。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当一块buffer就绪后，消费者就开始工作了，consumer对buffer的处理是被动的，它必须要等到一块buffer填充好才能工作，&lt;code&gt;那consumer怎么知道一块buffer已经填充好了&lt;/code&gt;？&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以我们顺着Layer的onFirstRef函数，里面还有一个对于消费者的封装：&lt;strong&gt;SurfaceFlingerConsumer&lt;/strong&gt;。为了方便，我再贴一遍Layer的onFirstRef函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; Layer::onFirstRef() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Creates a custom BufferQueue for SurfaceFlingerConsumer to use&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;IGraphicBufferProducer&amp;gt; producer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;IGraphicBufferConsumer&amp;gt; consumer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BufferQueue::createBufferQueue(&amp;amp;producer, &amp;amp;consumer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mProducer = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; MonitoredProducer(producer, mFlinger);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//创建一个SurfaceFlingerConsumer用于通知消费者消费&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; SurfaceFlingerConsumer(consumer, mTextureName);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer-&amp;gt;setConsumerUsageBits(getEffectiveUsage(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//给消费者设置监听者&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer-&amp;gt;setContentsChangedListener(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer-&amp;gt;setName(mName);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;为了方便起见，我们将BufferQueueConsumer和SurfaceFlingerConsumer的类图都贴出来：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%B8%83%29----%E5%88%9B%E5%BB%BA%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BAGraphicBuffer/Consumer.jpg&quot; alt=&quot;Consumer&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;为了通知消费消费GraphicBuffer，这里提供了另外一个类ConsumerListener，位于frameworks/native/include/gui/IConsumerListener.h：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;    ConsumerListener() &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; ~ConsumerListener() &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// onFrameAvailable is called from queueBuffer each time an additional&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// frame becomes available for consumption. This means that frames that&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// are queued while in asynchronous mode only trigger the callback if no&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// previous frames are pending. Frames queued while in synchronous mode&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// always trigger the callback.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// This is called without any lock held and can be called concurrently&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// by multiple threads.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;onFrameAvailable&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; &lt;span class=&quot;comment&quot;&gt;/* Asynchronous */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// onBuffersReleased is called to notify the buffer consumer that the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// BufferQueue has released its references to one or more GraphicBuffers&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// contained in its slots.  The buffer consumer should then call&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// BufferQueue::getReleasedBuffers to retrieve the list of buffers&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// This is called without any lock held and can be called concurrently&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// by multiple threads.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;onBuffersReleased&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; &lt;span class=&quot;comment&quot;&gt;/* Asynchronous */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// onSidebandStreamChanged is called to notify the buffer consumer that the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// BufferQueue&#39;s sideband buffer stream has changed. This is called when a&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// stream is first attached and when it is either detached or replaced by a&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// different stream.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;onSidebandStreamChanged&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; &lt;span class=&quot;comment&quot;&gt;/* Asynchronous */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;两个纯虚函数，当一块buffer可以被消费时，onFrameAvailable会被调用；当BufferQueue通知consumer它已经释放其mSlot中的一个或多个GraphicBuffer的引用时，会调用onBuffersReleased。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;那么什么时候注册的这个监听呢？我们需要跟随一下SurfaceFlingerConsumer 的构造函数，位于frameworks/native/services/surfaceflinger/SurfaceFlingerConsumer.h中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;SurfaceFlingerConsumer(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;IGraphicBufferConsumer&amp;gt;&amp;amp; consumer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; tex)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//调用了GLConsumer的构造函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    : GLConsumer(consumer, tex, GLConsumer::TEXTURE_EXTERNAL, &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;, &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mTransformToDisplayInverse(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们需要继续查看GLConsumer的构造函数，位于frameworks/native/libs/gui/GLConsumer.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;GLConsumer::GLConsumer(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;IGraphicBufferConsumer&amp;gt;&amp;amp; bq, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; tex,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; texTarget, &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; useFenceSync, &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; isControlledByApp) :&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ConsumerBase(bq, isControlledByApp), &lt;span class=&quot;comment&quot;&gt;//有调用了ConsumerBase的构造函数，猫腻应该在这里&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentTransform(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentFence(Fence::NO_FENCE),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentTimestamp(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentFrameNumber(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDefaultWidth(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDefaultHeight(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFilteringEnabled(&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mTexName(tex),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mUseFenceSync(useFenceSync),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mTexTarget(texTarget),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEglDisplay(EGL_NO_DISPLAY),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEglContext(EGL_NO_CONTEXT),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mAttached(&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ST_LOGV(&lt;span class=&quot;string&quot;&gt;&quot;GLConsumer&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;built_in&quot;&gt;memcpy&lt;/span&gt;(mCurrentTransformMatrix, mtxIdentity,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(mCurrentTransformMatrix));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mConsumer-&amp;gt;setConsumerUsageBits(DEFAULT_USAGE_FLAGS);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;又调用了ConsumerBase的构造函数，猫腻应该在这里，我们继续查看ConsumerBase的构造函数，位于frameworks/native/libs/gui/ConsumerBase.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;ConsumerBase::ConsumerBase(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;IGraphicBufferConsumer&amp;gt;&amp;amp; bufferQueue, &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; controlledByApp) :&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mAbandoned(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mConsumer(bufferQueue) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Choose a name using the PID and a process-unique ID.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mName = String8::format(&lt;span class=&quot;string&quot;&gt;&quot;unnamed-%d-%d&quot;&lt;/span&gt;, getpid(), createProcessUniqueId());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Note that we can&#39;t create an sp&amp;lt;...&amp;gt;(this) in a ctor that will not keep a&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// reference once the ctor ends, as that would cause the refcount of &#39;this&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// dropping to 0 at the end of the ctor.  Since all we need is a wp&amp;lt;...&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// that&#39;s what we create.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//创建监听者对象&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    wp&amp;lt;ConsumerListener&amp;gt; listener = &lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;ConsumerListener*&amp;gt;(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//包装成一个代理&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;IConsumerListener&amp;gt; proxy = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; BufferQueue::ProxyConsumerListener(listener);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//mConsumer调用consumerConnect函数，通过mConsumer，把consumerListener注册到服务者类bufferQueuecore中&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = mConsumer-&amp;gt;consumerConnect(proxy, controlledByApp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        CB_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;ConsumerBase: error connecting to BufferQueue: %s (%d)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                strerror(-err), err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mConsumer-&amp;gt;setConsumerName(mName);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面代码主要工作有：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）创建监听者对象；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）包装成一个代理；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）mConsumer调用consumerConnect函数，通过mConsumer，把consumerListener注册到服务者类bufferQueuecore中。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;那么注册操作就在于第三部。这里BufferQueueConsumer调用consumerConnect函数，位于frameworks/native/libs/gui/BufferQueueConsumer.h中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; status_t &lt;span class=&quot;title&quot;&gt;consumerConnect&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;IConsumerListener&amp;gt;&amp;amp; consumer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; controlledByApp)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; connect(consumer, controlledByApp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在头文件里定义了consumerConnect函数，调用connect函数，位于frameworks/native/libs/gui/BufferQueueConsumer.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; BufferQueueConsumer::connect(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;IConsumerListener&amp;gt;&amp;amp; consumerListener, &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; controlledByApp) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (consumerListener == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        BQ_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;connect(C): consumerListener may not be NULL&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; BAD_VALUE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BQ_LOGV(&lt;span class=&quot;string&quot;&gt;&quot;connect(C): controlledByApp=%s&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            controlledByApp ? &lt;span class=&quot;string&quot;&gt;&quot;true&quot;&lt;/span&gt; : &lt;span class=&quot;string&quot;&gt;&quot;false&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mCore-&amp;gt;mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mCore-&amp;gt;mIsAbandoned) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        BQ_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;connect(C): BufferQueue has been abandoned&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_INIT;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//这里把consumerListener注册到服务者类bufferQueuecore中&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCore-&amp;gt;mConsumerListener = consumerListener;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCore-&amp;gt;mConsumerControlledByApp = controlledByApp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;connect连接，经过层层调用，把listener监听注册到bufferQueuecore中，&lt;br&gt;这样bufferQueuecore就可以利用这个监听通知到具体的消费者。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接着就是设置监听者：mSurfaceFlingerConsumer-&amp;gt;setContentsChangedListener(this);我们可以看看他的操作：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlingerConsumer::setContentsChangedListener(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; wp&amp;lt;ContentsChangedListener&amp;gt;&amp;amp; listener) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//调用了ConsumerBase的setFrameAvailableListener函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    setFrameAvailableListener(listener);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mContentsChangedListener = listener;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/**ConsumerBase的setFrameAvailableListener函数**/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; ConsumerBase::setFrameAvailableListener(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; wp&amp;lt;FrameAvailableListener&amp;gt;&amp;amp; listener) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    CB_LOGV(&lt;span class=&quot;string&quot;&gt;&quot;setFrameAvailableListener&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFrameAvailableListener = listener;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这样就构成了完整的监听者模式了，有Observer，也有Observable。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这样就清楚了buffer的生产者，消费者，管理者之间的关系。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以稍微总结一下BufferQueue机制，借助&lt;code&gt;Chris Simmonds&lt;/code&gt;老爷子的话，就是如下内容：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mechanism for passing GraphicBuffers to SurfaceFlinger&lt;/li&gt;
&lt;li&gt;Contains an array of between 2 and 64 GraphicBuffers&lt;/li&gt;
&lt;li&gt;Uses interface IGraphicBufferAlloc to allocate buffers (see later)&lt;/li&gt;
&lt;li&gt;Provides two Binder interfaces：&lt;ul&gt;
&lt;li&gt;IGraphicBufferProducer for the client (Activity)&lt;/li&gt;
&lt;li&gt;IGraphicBufferConsumer for the consumer (SurfaceFlinger)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Buffers cycle between producer and consumer&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;分配图形缓冲区&quot;&gt;&lt;a href=&quot;#分配图形缓冲区&quot; class=&quot;headerlink&quot; title=&quot;分配图形缓冲区&quot;&gt;&lt;/a&gt;分配图形缓冲区&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;首先buffer是共享缓冲区，故肯定会涉及到互斥锁，所以buffer的状态也有很多种，一般buffer大致会经过&lt;strong&gt;FREE-&amp;gt;DEQUEUED-&amp;gt;QUEUED-&amp;gt;ACQUIRED-&amp;gt;FREE&lt;/strong&gt;这个过程。如果所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/file/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%8C%29----SurfaceFlinger%E6%A6%82%E8%BF%B0/PC3.jpg&quot; alt=&quot;bufferalloc&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;或者这样表示这个过程：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%B8%83%29----%E5%88%9B%E5%BB%BA%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BAGraphicBuffer/bufferalloc2.png&quot; alt=&quot;bufferalloc2&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;申请图形缓冲区&quot;&gt;&lt;a href=&quot;#申请图形缓冲区&quot; class=&quot;headerlink&quot; title=&quot;申请图形缓冲区&quot;&gt;&lt;/a&gt;申请图形缓冲区&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;前面看到，bufferqueuecore中mSlots数组管理缓冲区，最大容量是64，这个mSlots一开始静态分配了64个bufferslot大小的空间，但是其中的数据缓冲区不是一次性分配的，不然就太浪费空间了，所以缓冲区的空间分配是动态的，具体就是producer在dequeuebuffer时，如果没有获取到可用的缓冲区，那就要重新分配空间了。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;分配图形缓冲区，即GraphicBuffer，我们需要查看BufferQueueProducer的dequeuebuffer函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;96&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;97&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;98&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;99&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;100&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;101&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;102&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;103&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;104&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;105&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;106&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;107&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;108&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;109&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;110&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;111&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;112&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;113&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;114&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;115&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;116&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;117&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;118&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;119&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;120&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;121&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;122&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;123&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;124&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;125&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;126&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;127&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;128&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;129&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;130&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;131&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;132&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;133&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;134&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;135&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;136&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;137&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;138&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;139&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;140&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;141&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;142&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;143&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;144&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;145&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;146&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;147&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; BufferQueueProducer::dequeueBuffer(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; *outSlot,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;android::Fence&amp;gt; *outFence, &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; async,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; width, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; height, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; format, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; usage) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123; &lt;span class=&quot;comment&quot;&gt;// Autolock scope&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mCore-&amp;gt;mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mConsumerName = mCore-&amp;gt;mConsumerName;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;comment&quot;&gt;// Autolock scope&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BQ_LOGV(&lt;span class=&quot;string&quot;&gt;&quot;dequeueBuffer: async=%s w=%u h=%u format=%#x, usage=%#x&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            async ? &lt;span class=&quot;string&quot;&gt;&quot;true&quot;&lt;/span&gt; : &lt;span class=&quot;string&quot;&gt;&quot;false&quot;&lt;/span&gt;, width, height, format, usage);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//宽高不正常，则返回失败&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((width &amp;amp;&amp;amp; !height) || (!width &amp;amp;&amp;amp; height)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        BQ_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;dequeueBuffer: invalid size: w=%u h=%u&quot;&lt;/span&gt;, width, height);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; BAD_VALUE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//一些变量赋初值&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; returnFlags = NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLDisplay eglDisplay = EGL_NO_DISPLAY;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; attachedByConsumer = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123; &lt;span class=&quot;comment&quot;&gt;// Autolock scope&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mCore-&amp;gt;mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果正在申请Grabuffer，则要wait。里面是一个mIsAllocating标志位判断，如果为true则要等待&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mCore-&amp;gt;waitWhileAllocatingLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果format为0，则赋为初值PIXEL_FORMAT_RGBA_8888&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (format == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            format = mCore-&amp;gt;mDefaultBufferFormat;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Enable the usage bits the consumer requested&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        usage |= mCore-&amp;gt;mConsumerUsageBits;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; found;&lt;span class=&quot;comment&quot;&gt;//先在mSlot数组中查找FREE状态的slot，如果找到了就返回这个slot中的index。&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; status = waitForFreeSlotThenRelock(&lt;span class=&quot;string&quot;&gt;&quot;dequeueBuffer&quot;&lt;/span&gt;, async,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;amp;found, &amp;amp;returnFlags);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (status != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; status;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// This should not happen&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//这种情况一般不会发生，因为如何found是INVALID_BUFFER_SLOT状态，上面的status就不会是NO_Error,就不会走到这里&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (found == BufferQueueCore::INVALID_BUFFER_SLOT) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            BQ_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;dequeueBuffer: no available buffer slots&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -EBUSY;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//将找到的slot的index赋给外面传入的outSlot指向内容&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        *outSlot = found;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ATRACE_BUFFER_INDEX(found);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        attachedByConsumer = mSlots[found].mAttachedByConsumer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; useDefaultSize = !width &amp;amp;&amp;amp; !height;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (useDefaultSize) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            width = mCore-&amp;gt;mDefaultWidth;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            height = mCore-&amp;gt;mDefaultHeight;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//改变BufferState状态为DEQUEUED&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSlots[found].mBufferState = BufferSlot::DEQUEUED;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//然后将返回index的slot的Graphicbuffer赋给buffer变量&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;GraphicBuffer&amp;gt;&amp;amp; buffer(mSlots[found].mGraphicBuffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//判断这个GraphicBuffer是否需要重新分配空间，判断条件就是buffer为空，因为它初始值是null，第一次使用它需要分配空间，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果不为null，但是buffer的width、height、format、usage属性跟要求的不一致，也要重新分配&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((buffer == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                (&lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;&amp;gt;(buffer-&amp;gt;width) != width) ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                (&lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;&amp;gt;(buffer-&amp;gt;height) != height) ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                (&lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;&amp;gt;(buffer-&amp;gt;format) != format) ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ((&lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;&amp;gt;(buffer-&amp;gt;usage) &amp;amp; usage) != usage))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//如果需要重新分配GraphicBuffer，先初始化这些变量&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSlots[found].mAcquireCalled = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSlots[found].mGraphicBuffer = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSlots[found].mRequestBufferCalled = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSlots[found].mEglDisplay = EGL_NO_DISPLAY;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSlots[found].mEglFence = EGL_NO_SYNC_KHR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSlots[found].mFence = Fence::NO_FENCE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//增加BUFFER_NEEDS_REALLOCATION标志，已重新分配GraphicBuffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            returnFlags |= BUFFER_NEEDS_REALLOCATION;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (CC_UNLIKELY(mSlots[found].mFence == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            BQ_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;dequeueBuffer: about to return a NULL fence - &quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;string&quot;&gt;&quot;slot=%d w=%d h=%d format=%u&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    found, buffer-&amp;gt;width, buffer-&amp;gt;height, buffer-&amp;gt;format);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//给一些临时变量赋值&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        eglDisplay = mSlots[found].mEglDisplay;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        eglFence = mSlots[found].mEglFence;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        *outFence = mSlots[found].mFence;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//给fence变量赋初值&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSlots[found].mEglFence = EGL_NO_SYNC_KHR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSlots[found].mFence = Fence::NO_FENCE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;comment&quot;&gt;// Autolock scope&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果需要重新分配GraphicBuffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (returnFlags &amp;amp; BUFFER_NEEDS_REALLOCATION) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; error;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        BQ_LOGV(&lt;span class=&quot;string&quot;&gt;&quot;dequeueBuffer: allocating a new buffer for slot %d&quot;&lt;/span&gt;, *outSlot);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//需要重新分配，调用BufferQueueCore中的GraphicBufferAlloc中函数createGraphicBuffer，生成一个newGraphicBuffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;GraphicBuffer&amp;gt; graphicBuffer(mCore-&amp;gt;mAllocator-&amp;gt;createGraphicBuffer(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    width, height, format, usage, &amp;amp;error));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (graphicBuffer == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            BQ_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;dequeueBuffer: createGraphicBuffer failed&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; error;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#123; &lt;span class=&quot;comment&quot;&gt;// Autolock scope&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mCore-&amp;gt;mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mCore-&amp;gt;mIsAbandoned) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                BQ_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;dequeueBuffer: BufferQueue has been abandoned&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_INIT;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;////新分配的buffer，将slot的mFrameNumber 置为最大。mFrameNumber 用于LRU排序&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSlots[*outSlot].mFrameNumber = UINT32_MAX;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//将分配的buffer赋给slot中的mGraphicBuffer &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSlots[*outSlot].mGraphicBuffer = graphicBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;comment&quot;&gt;// Autolock scope&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (attachedByConsumer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        returnFlags |= BUFFER_NEEDS_REALLOCATION;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果eglFence不等于EGL_NO_SYNC_KHR。Fence我们后面会讲到，一种围栏机制&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (eglFence != EGL_NO_SYNC_KHR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//等待Buffer状态就绪，然后fence围栏放行&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;number&quot;&gt;1000000000&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// If something goes wrong, log the error, but return the buffer without&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// synchronizing access to it. It&#39;s too late at this point to abort the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// dequeue operation.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (result == EGL_FALSE) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            BQ_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;dequeueBuffer: error %#x waiting for fence&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    eglGetError());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (result == EGL_TIMEOUT_EXPIRED_KHR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            BQ_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;dequeueBuffer: timeout waiting for fence&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        eglDestroySyncKHR(eglDisplay, eglFence);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BQ_LOGV(&lt;span class=&quot;string&quot;&gt;&quot;dequeueBuffer: returning slot=%d/%&quot;&lt;/span&gt; PRIu64 &lt;span class=&quot;string&quot;&gt;&quot; buf=%p flags=%#x&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            *outSlot,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSlots[*outSlot].mFrameNumber,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSlots[*outSlot].mGraphicBuffer-&amp;gt;handle, returnFlags);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; returnFlags;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;代码虽然多，但是逻辑不复杂，我们分步查看：&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）先在mSlot数组中查找FREE状态的slot，如果找到了就返回这个slot中的index。这个操作是调用了waitForFreeSlotThenRelock函数，我们看看这个函数的实现：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;96&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;97&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;98&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;99&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;100&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;101&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;102&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;103&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;104&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;105&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;106&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;107&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;108&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;109&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;110&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;111&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;112&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;113&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;114&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;115&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;116&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;117&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;118&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;119&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;120&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;121&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;122&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;123&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;124&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;125&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;126&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;127&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;128&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;129&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;130&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;131&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;132&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;133&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;134&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;135&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;136&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;137&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;138&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;139&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; BufferQueueProducer::waitForFreeSlotThenRelock(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt;* caller,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; async, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;* found, &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt;* returnFlags) &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; tryAgain = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;span class=&quot;comment&quot;&gt;//默认是true&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (tryAgain) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mCore-&amp;gt;mIsAbandoned) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//如果没有初始化，BufferQueue被abandoned&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            BQ_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;%s: BufferQueue has been abandoned&quot;&lt;/span&gt;, caller);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_INIT;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//getMaxBufferCountLocked returns the maximum number of buffers that can be allocated at once&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//注释还有一些，不贴了。就是获取一次申请的buffer的最大值。查看了代码，就是所有状态的buffer个数。&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; maxBufferCount = mCore-&amp;gt;getMaxBufferCountLocked(async);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果async为true，即异步操作，并且mOverrideMaxBufferCount不为0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//（一般mOverrideMaxBufferCount是在BufferQueueProducer调用setBufferCount函数改变，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//这个函数会更新mSlot中所有Slot的状态为未分配的，并把ower还给BufferQueue）&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (async &amp;amp;&amp;amp; mCore-&amp;gt;mOverrideMaxBufferCount) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;FIXME:&lt;/span&gt; Some drivers are manually setting the buffer count&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// (which they shouldn&#39;t), so we do this extra test here to&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// handle that case. This is TEMPORARY until we get this fixed.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//因为是异步的关系，一些驱动会修改buffer count，但是返回不及时，所以这两个值可能不相等&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mCore-&amp;gt;mOverrideMaxBufferCount &amp;lt; maxBufferCount) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                BQ_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;%s: async mode is invalid with buffer count override&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        caller);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; BAD_VALUE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Free up any buffers that are in slots beyond the max buffer count&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//释放所有超出buffer数组最大数64的buffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; s = maxBufferCount; s &amp;lt; BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            assert(mSlots[s].mBufferState == BufferSlot::FREE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mSlots[s].mGraphicBuffer != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mCore-&amp;gt;freeBufferLocked(s);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                *returnFlags |= RELEASE_ALL_BUFFERS;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Look for a free buffer to give to the client&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//开始查找FREE状态的Buffer，并返回&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        *found = BufferQueueCore::INVALID_BUFFER_SLOT;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; dequeuedCount = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; acquiredCount = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; s = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; s &amp;lt; maxBufferCount; ++s) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt; (mSlots[s].mBufferState) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; BufferSlot::DEQUEUED:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    ++dequeuedCount;&lt;span class=&quot;comment&quot;&gt;//DEQUEUED + 1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; BufferSlot::ACQUIRED:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    ++acquiredCount;&lt;span class=&quot;comment&quot;&gt;//ACQUIRED + 1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; BufferSlot::FREE:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// We return the oldest of the free buffers to avoid&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// stalling the producer if possible, since the consumer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// may still have pending reads of in-flight buffers&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//返回最老的FREE buffer，为了避免当consumer还在等待消费pending的正在起飞的buffer时候，producer突然GG了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (*found == BufferQueueCore::INVALID_BUFFER_SLOT ||&lt;span class=&quot;comment&quot;&gt;//第一次找到FREE buffer，会将found指针指向这个index&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            &lt;span class=&quot;comment&quot;&gt;//下次来的FREE buffer，就和上此找到的buffer对比slot的mFrameNumber ，找到mFrameNumber 最小的。&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            &lt;span class=&quot;comment&quot;&gt;//这个就是根绝mFrameNumber 的大小进行LRU排序，最新的就是mFrameNumber 最大的，最老的就是mFrameNumber 最小的&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            mSlots[s].mFrameNumber &amp;lt; mSlots[*found].mFrameNumber) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        *found = s;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;default&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Producers are not allowed to dequeue more than one buffer if they&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// did not set a buffer count&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//Producers 如果没有调用setBufferCount是不允许dequeue buffer的&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mCore-&amp;gt;mOverrideMaxBufferCount &amp;amp;&amp;amp; dequeuedCount) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            BQ_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;%s: can&#39;t dequeue multiple buffers without setting the &quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;string&quot;&gt;&quot;buffer count&quot;&lt;/span&gt;, caller);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; INVALID_OPERATION;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// See whether a buffer has been queued since the last&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// setBufferCount so we know whether to perform the min undequeued&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// buffers check below&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//在queueBuffer调用后，mBufferHasBeenQueued会置为true&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果在上次setBufferCount调用后，当buffer被queue进入BufferQueue，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//这时候需要检查undequeue的数量是否大于最小的临界值&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mCore-&amp;gt;mBufferHasBeenQueued) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// Make sure the producer is not trying to dequeue more buffers&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// than allowed&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//总count - dequeue的count = undequeue的count&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; newUndequeuedCount =&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                maxBufferCount - (dequeuedCount + &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; minUndequeuedCount =&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mCore-&amp;gt;getMinUndequeuedBufferCountLocked(async);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (newUndequeuedCount &amp;lt; minUndequeuedCount) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                BQ_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;%s: min undequeued buffer count (%d) exceeded &quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;string&quot;&gt;&quot;(dequeued=%d undequeued=%d)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        caller, minUndequeuedCount,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        dequeuedCount, newUndequeuedCount);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; INVALID_OPERATION;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// If we disconnect and reconnect quickly, we can be in a state where&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// our slots are empty but we have many buffers in the queue. This can&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// cause us to run out of memory if we outrun the consumer. Wait here if&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// it looks like we have too many buffers queued up.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果我们调用disconnect后迅速的reconnect，会出现mSlot数组为空但是mQueue队列中的BufferItem不为空&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//所以这样会造成内存耗尽的后果&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//就是判断放入mQueue中BufferItem的个数是否大于mSlot中的个数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//mQueue是用来存放申请的缓冲区的，是一个Vector&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; tooManyBuffers = mCore-&amp;gt;mQueue.size()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            &amp;gt; &lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt;&amp;gt;(maxBufferCount);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (tooManyBuffers) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            BQ_LOGV(&lt;span class=&quot;string&quot;&gt;&quot;%s: queue size is %zu, waiting&quot;&lt;/span&gt;, caller,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    mCore-&amp;gt;mQueue.size());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// If no buffer is found, or if the queue has too many buffers&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// outstanding, wait for a buffer to be acquired or released, or for the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// max buffer count to change.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果没有找到FREE的buffer，或者mQueue中有太多buffer占据内存未释放&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//那么等待buffer被acquired or released；&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//或者等待最大buffer个数改变&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT) ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                   tooManyBuffers;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (tryAgain) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// Return an error if we&#39;re in non-blocking mode (producer and&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// consumer are controlled by the application).&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// However, the consumer is allowed to briefly acquire an extra&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// buffer (which could cause us to have to wait here), which is&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// okay, since it is only used to implement an atomic acquire +&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// release (e.g., in GLConsumer::updateTexImage())&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mCore-&amp;gt;mDequeueBufferCannotBlock &amp;amp;&amp;amp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    (acquiredCount &amp;lt;= mCore-&amp;gt;mMaxAcquiredBufferCount)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; WOULD_BLOCK;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//等待有buffer可以返回&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mCore-&amp;gt;mDequeueCondition.wait(mCore-&amp;gt;mMutex);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;comment&quot;&gt;// while (tryAgain)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;代码虽然多，但是大多数都是处理特殊情况的。核心就是从现存maxBufferCount找出FREE状态的slot，然后根据LRU匹配，取出最老的slot，然后返回index给found指针内容。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这样取出来FREE的slot（如果能找到）。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果所有的buffer都不是free的，则等待。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）将找到的buf所对应的状态修改为DEQUEUED；&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）然后将上面查询mSlot中返回index的slot的Graphicbuffer赋给buffer变量；&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）判断这个GraphicBuffer是否需要重新分配空间，判断条件就是buffer为空，因为它初始值是null，第一次使用它需要分配空间；如果不为null，但是buffer的width、height、format、usage属性跟要求的不一致，也要重新分配，并打上BUFFER_NEEDS_REALLOCATION标志位。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;5）如果上面的buffer为null，则需要重新分配GraphicBuffer，调用BufferQueueCore中的GraphicBufferAlloc中函数createGraphicBuffer，生成一个new GraphicBuffer。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;6）等待eglFence状态就绪。Fence机制我们以后会讲到。&lt;/p&gt;
&lt;h2 id=&quot;创建图形缓冲区&quot;&gt;&lt;a href=&quot;#创建图形缓冲区&quot; class=&quot;headerlink&quot; title=&quot;创建图形缓冲区&quot;&gt;&lt;/a&gt;创建图形缓冲区&lt;/h2&gt;&lt;h3 id=&quot;GraphicBuffer创建&quot;&gt;&lt;a href=&quot;#GraphicBuffer创建&quot; class=&quot;headerlink&quot; title=&quot;GraphicBuffer创建&quot;&gt;&lt;/a&gt;GraphicBuffer创建&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以上述流程的核心是GraphicBuffer的分配，我们需要沿着上面继续分析。因此最后BufferQueueProducer中的dequeueBuffer函数中调用mCore-&amp;gt;mAllocator的createGraphicBuffer函数就是调用了GraphicBufferAlloc的createGraphicBufferAlloc函数。mAllocator的类型为sp&amp;lt; IGraphicBufferAlloc &amp;gt;，要跨进程调用SurfaceFlinger的createGraphicBufferAlloc函数，上面讲过了。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面刚刚说mAllocator的类型为sp&amp;lt; IGraphicBufferAlloc &amp;gt;，所以创建GraphicBuffer的函数createGraphicBuffer也需要Bp/Bn 的IPC跨进程调用过程。GraphicBuffer通过Binder传递对象是Parcel类型可序列化的，所以他要从模板类Flattenable派生。因为这个牵扯到&lt;strong&gt;内存缓冲区的fd传递到客户进程&lt;/strong&gt;，所以我们放到后面讲。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以我们先忽略IPC过程，直接查看生成结果，位于frameworks/native/libs/gui/GraphicBufferAlloc.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sp&amp;lt;GraphicBuffer&amp;gt; GraphicBufferAlloc::createGraphicBuffer(&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; h,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PixelFormat format, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; usage, &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt;* error) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//创建一个GraphicBuffer对象&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;GraphicBuffer&amp;gt; graphicBuffer(&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; GraphicBuffer(w, h, format, usage));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = graphicBuffer-&amp;gt;initCheck();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    *error = err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; || graphicBuffer-&amp;gt;handle == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == NO_MEMORY) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            GraphicBuffer::dumpAllocationsToSystemLog();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) &quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             &lt;span class=&quot;string&quot;&gt;&quot;failed (%s), handle=%p&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                w, h, strerror(-err), graphicBuffer-&amp;gt;handle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; graphicBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面创建一个GraphicBuffer对象，我们看看GraphicBuffer的构造函数，位于frameworks/native/libs/ui/GraphicBuffer.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;GraphicBuffer::GraphicBuffer(&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; h, &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PixelFormat reqFormat, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; reqUsage)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mInitCheck(NO_ERROR), mId(getUniqueId())&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    width  = &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    height = &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    stride = &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    format = &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    usage  = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    handle = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//这里调用了initSize函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mInitCheck = initSize(w, h, reqFormat, reqUsage);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;构造函数给一些变量赋了初值，并调用了initSize函数，我们看看这个函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; GraphicBuffer::initSize(&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; h, PixelFormat format,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; reqUsage)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//获取一个GraphicBufferAllocator对象，它是个单例&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    GraphicBufferAllocator&amp;amp; allocator = GraphicBufferAllocator::get();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//调用allocator 的alloc函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = allocator.alloc(w, h, format, reqUsage, &amp;amp;handle, &amp;amp;stride);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;-&amp;gt;width  = w;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;-&amp;gt;height = h;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;-&amp;gt;format = format;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;-&amp;gt;usage  = reqUsage;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;先创建一个GraphicBufferAllocator的单例对象，我们先看看它的构造函数，位于frameworks/native/libs/ui/GraphicBufferAllocator.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;alloc_device_t&lt;/span&gt;  *mAllocDev;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;GraphicBufferAllocator::GraphicBufferAllocator()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    : mAllocDev(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;hw_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* module;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//加载gralloc设备&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &amp;amp;module);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGE_IF(err, &lt;span class=&quot;string&quot;&gt;&quot;FATAL: can&#39;t find the %s module&quot;&lt;/span&gt;, GRALLOC_HARDWARE_MODULE_ID);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//打开gralloc设备&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        gralloc_open(module, &amp;amp;mAllocDev);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;GraphicBufferAllocator构造函数里主要是加载了gralloc设备，然后打开它，因此mAllocDev指向了Gralloc模块。这一部分可以查看&lt;a href=&quot;http://windrunnerlihuan.com/2017/03/12/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B8%80-Android%E5%9B%BE%E5%BD%A2%E6%98%BE%E7%A4%BA%E4%B9%8BHAL%E5%B1%82Gralloc%E6%A8%A1%E5%9D%97%E5%AE%9E%E7%8E%B0/&quot;&gt;Android SurfaceFlinger 学习之路(一)—-Android图形显示之HAL层Gralloc模块实现&lt;/a&gt;，&lt;strong&gt;Gralloc模块的加载过程、Gralloc设备的打开过程&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;加载完Gralloc模块，并打开之后，接着就是分配图形缓冲区了。我们可以继续往下看看是不是，查看GraphicBufferAllocator的alloc函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; GraphicBufferAllocator::alloc(&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; h, PixelFormat format,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; usage, &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt;* handle, &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt;* stride)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// make sure to not allocate a N x 0 or 0 x N buffer, since this is&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// allowed from an API stand-point allocate a 1x1 buffer instead.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!w || !h)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        w = h = &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// we have a h/w allocator and h/w buffer is requested&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//这里内部是调用Gralloc模块中的函数gralloc_alloc来分配一块图形缓冲区&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    err = mAllocDev-&amp;gt;alloc(mAllocDev, w, h, format, usage, handle, stride);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGW_IF(err, &lt;span class=&quot;string&quot;&gt;&quot;alloc(%u, %u, %d, %08x, ...) failed %d (%s)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            w, h, format, usage, err, strerror(-err));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Mutex::Autolock _l(sLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        KeyedVector&amp;lt;&lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;alloc_rec_t&lt;/span&gt;&amp;gt;&amp;amp; &lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;(sAllocList);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; bpp = bytesPerPixel(format);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (bpp &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// probably a HAL custom format. in any case, we don&#39;t know&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// what its pixel size is.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            bpp = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;alloc_rec_t&lt;/span&gt; rec;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        rec.w = w;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        rec.h = h;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        rec.s = *stride;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        rec.format = format;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        rec.usage = usage;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        rec.size = h * stride[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;] * bpp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;built_in&quot;&gt;list&lt;/span&gt;.add(*handle, rec);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里调用alloc分配了一块共享的内存缓冲区，就是我们的图形缓冲区。内部是调用Gralloc模块中的函数gralloc_alloc，可以产查看&lt;a href=&quot;http://windrunnerlihuan.com/2017/03/12/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B8%80-Android%E5%9B%BE%E5%BD%A2%E6%98%BE%E7%A4%BA%E4%B9%8BHAL%E5%B1%82Gralloc%E6%A8%A1%E5%9D%97%E5%AE%9E%E7%8E%B0/&quot;&gt;Android SurfaceFlinger 学习之路(一)—-Android图形显示之HAL层Gralloc模块实现&lt;/a&gt;，&lt;strong&gt;分配图形缓冲区&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这样我们GraphicBuffer的创建工作就完成了。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;既然GraphicBuffer中的缓冲区是共享内存，我们知道使用共享内存需要传递共享内存的句柄fd。下面我们看看是如何传到客户进程的，填掉我们上面的坑。&lt;/p&gt;
&lt;h3 id=&quot;内存缓冲区映射到应用进程&quot;&gt;&lt;a href=&quot;#内存缓冲区映射到应用进程&quot; class=&quot;headerlink&quot; title=&quot;内存缓冲区映射到应用进程&quot;&gt;&lt;/a&gt;内存缓冲区映射到应用进程&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;GraphicBuffer类是从模板类Flattenable派生，这个派生类可以通过Parcel传递，通常派生类需要重载flatten和unflatten方法，用于对象的序列化和反序列化。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;为了方便分析，我们可以看看GraphicBuffer的类图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%B8%83%29----%E5%88%9B%E5%BB%BA%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BAGraphicBuffer/GraphicBuffer.jpg&quot; alt=&quot;GraphicBuffer&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面说到mAllocator的类型为sp&amp;lt; IGraphicBufferAlloc &amp;gt;，它的创建GraphicBuffer的函数createGraphicBuffer也需要Bp/Bn 的IPC跨进程调用过程，序列化传递和反序列话取出这里用于IPC传递数据，我们可以在这里看看客户端和服务端的工作流程。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们先看看客户端Bp端，位于frameworks/native/libs/gui/IGraphicBufferAlloc.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; BpGraphicBufferAlloc : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; BpInterface&amp;lt;IGraphicBufferAlloc&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BpGraphicBufferAlloc(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;IBinder&amp;gt;&amp;amp; impl)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        : BpInterface&amp;lt;IGraphicBufferAlloc&amp;gt;(impl)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//客户端创建图形缓冲区函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; sp&amp;lt;GraphicBuffer&amp;gt; createGraphicBuffer(&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; h,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            PixelFormat format, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; usage, &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt;* error) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Parcel data, reply;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        data.writeInterfaceToken(IGraphicBufferAlloc::getInterfaceDescriptor());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        data.writeInt32(w);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        data.writeInt32(h);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        data.writeInt32(format);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        data.writeInt32(usage);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//通过binder驱动，执行服务端对应函数。这里服务端是将创建的GraphicBuffer序列化后，塞给replay&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        remote()-&amp;gt;transact(CREATE_GRAPHIC_BUFFER, data, &amp;amp;reply);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;GraphicBuffer&amp;gt; graphicBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; result = reply.readInt32();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (result == NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//创建一个空壳子&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            graphicBuffer = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; GraphicBuffer();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//然后客户端从服务端（SurfaceFlinger）返回的序列化后的replay，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//反序列化出Graphicbuffer，放入空壳子中&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            result = reply.read(*graphicBuffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// reply.readStrongBinder();&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// here we don&#39;t even have to read the BufferReference from&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// the parcel, it&#39;ll die with the parcel.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        *error = result;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; graphicBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;客户端这里主要通过binder驱动，取出从服务端返回的序列化后的对象replay，然后自己造一个空壳子，然后读取replay信息，反序列化出GraphicBuffer。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;那么服务端（SurfaceFlinger）创建GraphicBuffer并反序列化就在Bn端，我们看看Bn端实现，同样位于位于frameworks/native/libs/gui/IGraphicBufferAlloc.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; BnGraphicBufferAlloc::onTransact(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; code, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Parcel&amp;amp; data, Parcel* reply, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// codes that don&#39;t require permission check&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* BufferReference just keeps a strong reference to a&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * GraphicBuffer until it is destroyed (that is, until&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * no local or remote process have a reference to it).&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; BufferReference : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; BBinder &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;GraphicBuffer&amp;gt; buffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        BufferReference(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;GraphicBuffer&amp;gt;&amp;amp; buffer) : buffer(buffer) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt;(code) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; CREATE_GRAPHIC_BUFFER: &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            CHECK_INTERFACE(IGraphicBufferAlloc, data, reply);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; w = data.readInt32();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; h = data.readInt32();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            PixelFormat format = data.readInt32();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; usage = data.readInt32();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; error;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//调用GraphicBufferAlloc的createGraphicBuffer函数，创建一个GraphicBuffer实例&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sp&amp;lt;GraphicBuffer&amp;gt; result =&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    createGraphicBuffer(w, h, format, usage, &amp;amp;error);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            reply-&amp;gt;writeInt32(error);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (result != &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;////GraphicBuffer进行序列化，传给client&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                reply-&amp;gt;write(*result);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// We add a BufferReference to this parcel to make sure the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// buffer stays alive until the GraphicBuffer object on&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// the other side has been created.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// This is needed so that the buffer handle can be&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// registered before the buffer is destroyed on implementations&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// that do not use file-descriptors to track their buffers.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                reply-&amp;gt;writeStrongBinder( &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; BufferReference(result) );&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;default&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; BBinder::onTransact(code, data, reply, flags);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;GraphicBufferAlloc的createGraphicBuffer函数我们上面分析过了。这样就将创建的GraphicBuffer实例序列化后，在通过binder驱动传给client。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们知道，一个对象要在进程间传输必须继承于Flattenable类，并且实现flatten和unflatten方法，flatten方法用于序列化该对象，unflatten方法用于反序列化对象。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%B8%83%29----%E5%88%9B%E5%BB%BA%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BAGraphicBuffer/flatten.jpg&quot; alt=&quot;flatten&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面说到GraphicBuffer中的缓冲区是共享内存，使用共享内存需要传递共享内存的句柄fd，那么这个fd的传递就应该在GraphicBuffer的序列化/反序列化中，我们就来看看这个过程。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里我先回顾一下&lt;a href=&quot;http://windrunnerlihuan.com/2017/03/12/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B8%80-Android%E5%9B%BE%E5%BD%A2%E6%98%BE%E7%A4%BA%E4%B9%8BHAL%E5%B1%82Gralloc%E6%A8%A1%E5%9D%97%E5%AE%9E%E7%8E%B0/&quot;&gt;Android SurfaceFlinger 学习之路(一)—-Android图形显示之HAL层Gralloc模块实现&lt;/a&gt;的内容：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;图形缓冲区可以从系统帧缓冲区分配也可以从内存中分配，分配一个图形缓冲区后还需要将该图形缓冲区映射到分配该buffer的进程地址空间来，在Android系统中，图形缓冲区的管理由SurfaceFlinger服务来负责。在系统帧缓冲区中分配的图形缓冲区是在SurfaceFlinger服务中使用，而在内存中分配的图形缓冲区既可以在SurfaceFlinger服务中使用，也可以在其它的应用程序中使用。当其它的应用程序需要使用图形缓冲区的时候，它们就会请求SurfaceFlinger服务为它们分配并将SurfaceFlinger服务返回来的图形缓冲区映射到应用程序进程地址空间。在从内存中分配buffer时，已经将分配的buffer映射到了SurfaceFlinger服务进程地址空间，如果该buffer是应用程序请求SurfaceFlinger服务为它们分配的，那么还需要将SurfaceFlinger服务返回来的图形缓冲区映射到应用程序进程地址空间。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%B8%83%29----%E5%88%9B%E5%BB%BA%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BAGraphicBuffer/gralloc.jpg&quot; alt=&quot;gralloc&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;GraphicBuffer类从模板类Flattenable派生，这个派生类可以通过Parcel传递，通常派生类需要重载flatten和unflatten方法，用于对象的序列化和反序列化。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）将一个对象写入到Parcel中，需要使用flatten函数序列化该对象，我们先来看下flatten函数：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;status_t GraphicBuffer::flatten(void*&amp;amp; buffer, size_t&amp;amp; size, int*&amp;amp; fds, size_t&amp;amp; count) const &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    size_t sizeNeeded = GraphicBuffer::getFlattenedSize();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (size &amp;lt; sizeNeeded) return NO_MEMORY;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    size_t fdCountNeeded = GraphicBuffer::getFdCount();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (count &amp;lt; fdCountNeeded) return NO_MEMORY;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    int32_t* buf = static_cast&amp;lt;int32_t*&amp;gt;(buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    buf[0] = &#39;GBFR&#39;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    buf[1] = width;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    buf[2] = height;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    buf[3] = stride;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    buf[4] = format;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    buf[5] = usage;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    buf[6] = static_cast&amp;lt;int32_t&amp;gt;(mId &amp;gt;&amp;gt; 32);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    buf[7] = static_cast&amp;lt;int32_t&amp;gt;(mId &amp;amp; 0xFFFFFFFFull);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    buf[8] = 0;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    buf[9] = 0;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (handle) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        buf[8] = handle-&amp;gt;numFds;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        buf[9] = handle-&amp;gt;numInts;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        native_handle_t const* const h = handle;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //把handle中的data复制到fds中 &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        memcpy(fds,     h-&amp;gt;data,             h-&amp;gt;numFds*sizeof(int));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        memcpy(&amp;amp;buf[10], h-&amp;gt;data + h-&amp;gt;numFds, h-&amp;gt;numInts*sizeof(int));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    buffer = reinterpret_cast&amp;lt;void*&amp;gt;(static_cast&amp;lt;int*&amp;gt;(buffer) + sizeNeeded);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    size -= sizeNeeded;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (handle) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        fds += handle-&amp;gt;numFds;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        count -= handle-&amp;gt;numFds;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    return NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个handle类型为native_handle_t ，且typedef成了buffer_handle_t，如果忘记了这一部分，可以查看&lt;a href=&quot;http://windrunnerlihuan.com/2017/03/12/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B8%80-Android%E5%9B%BE%E5%BD%A2%E6%98%BE%E7%A4%BA%E4%B9%8BHAL%E5%B1%82Gralloc%E6%A8%A1%E5%9D%97%E5%AE%9E%E7%8E%B0/&quot;&gt;Android SurfaceFlinger 学习之路(一)—-Android图形显示之HAL层Gralloc模块实现&lt;/a&gt;。我们贴一下它的定义：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; native_handle  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; version; &lt;span class=&quot;comment&quot;&gt;//设置为结构体native_handle_t的大小，用来标识结构体native_handle_t的版本  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; numFds;  &lt;span class=&quot;comment&quot;&gt;//表示结构体native_handle_t所包含的文件描述符的个数，这些文件描述符保存在成员变量data所指向的一块缓冲区中。  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; numInts; &lt;span class=&quot;comment&quot;&gt;//表示结构体native_handle_t所包含的整数值的个数，这些整数保存在成员变量data所指向的一块缓冲区中。  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; data[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]; &lt;span class=&quot;comment&quot;&gt;//指向的一块缓冲区中  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125; &lt;span class=&quot;keyword&quot;&gt;native_handle_t&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以我们回到flatten函数中，fds参数用来传递文件句柄，函数把handle中的表示指向图形缓冲区文件描述符句柄复制到fds中，因此这些句柄就能通过binder传递到目标进程中去。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）在应用程序读取来自服务进程的GraphicBuffer对象时，也就是result = reply.read(*p)，会调用GraphicBuffer类的unflatten函数进行反序列化过程：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;status_t GraphicBuffer::unflatten(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        void const*&amp;amp; buffer, size_t&amp;amp; size, int const*&amp;amp; fds, size_t&amp;amp; count) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (size &amp;lt; 8*sizeof(int)) return NO_MEMORY;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    int const* buf = static_cast&amp;lt;int const*&amp;gt;(buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (buf[0] != &#39;GBFR&#39;) return BAD_TYPE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const size_t numFds  = buf[8];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const size_t numInts = buf[9];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const size_t sizeNeeded = (10 + numInts) * sizeof(int);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (size &amp;lt; sizeNeeded) return NO_MEMORY;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    size_t fdCountNeeded = 0;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (count &amp;lt; fdCountNeeded) return NO_MEMORY;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (handle) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // free previous handle if any&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        free_handle();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (numFds || numInts) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        width  = buf[1];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        height = buf[2];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        stride = buf[3];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        format = buf[4];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        usage  = buf[5];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //创建一个native_handle对象&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        native_handle* h = native_handle_create(numFds, numInts);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //将fds复制到native_handle对象的data中，和flatten操作相反&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        memcpy(h-&amp;gt;data,          fds,     numFds*sizeof(int));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        memcpy(h-&amp;gt;data + numFds, &amp;amp;buf[10], numInts*sizeof(int));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        handle = h;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; else &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        width = height = stride = format = usage = 0;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        handle = NULL;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mId = static_cast&amp;lt;uint64_t&amp;gt;(buf[6]) &amp;lt;&amp;lt; 32;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mId |= static_cast&amp;lt;uint32_t&amp;gt;(buf[7]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mOwner = ownHandle;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (handle != 0) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //使用GraphicBufferMapper将服务端创建的图形缓冲区映射到当前进程地址空间  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        status_t err = mBufferMapper.registerBuffer(handle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            width = height = stride = format = usage = 0;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            handle = NULL;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ALOGE(&quot;unflatten: registerBuffer failed: %s (%d)&quot;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    strerror(-err), err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            return err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    buffer = reinterpret_cast&amp;lt;void const*&amp;gt;(static_cast&amp;lt;int const*&amp;gt;(buffer) + sizeNeeded);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    size -= sizeNeeded;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    fds += numFds;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    count -= numFds;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    return NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;调用unflatten函数时，共享区的文件句柄已经准备好了，但是内存还没有进行映射，调用了mBufferMapper.registerBuffer函数来进行内存映射。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;GraphicBufferMapper是单例的模板类派生的，mBufferMapper对象在GraphicBuffer的构造函数中初始化赋值了，上面我们列出过了。我们看看GraphicBufferMapper的构造函数，位于frameworks/native/libs/ui/GraphicBufferMapper.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;GraphicBufferMapper::GraphicBufferMapper()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    : mAllocMod(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;hw_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* module;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//加载gralloc模块&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &amp;amp;module);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGE_IF(err, &lt;span class=&quot;string&quot;&gt;&quot;FATAL: can&#39;t find the %s module&quot;&lt;/span&gt;, GRALLOC_HARDWARE_MODULE_ID);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;////将hw_module_t的指针转换为gralloc_module_t类型指针 &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mAllocMod = (&lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; *)module;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里根据模块ID加载Gralloc模块，并得到Gralloc模块的HMI符号首地址，并强制转换为gralloc_module_t类型指针。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们接着看下GraphicBufferMapper::registerBuffer函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; GraphicBufferMapper::registerBuffer(&lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt; handle)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//将服务端创建的图形缓冲区映射到当前进程地址空间&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    err = mAllocMod-&amp;gt;registerBuffer(mAllocMod, handle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGW_IF(err, &lt;span class=&quot;string&quot;&gt;&quot;registerBuffer(%p) failed %d (%s)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            handle, err, strerror(-err));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;调用了mAllocMod的registerBuffer函数，mAllocMod同样是指向了Gralloc模块的指针，因此实际是调用了Gralloc模块的gralloc_register_buffer函数。这个函数就是调用了mmap来进行共享内存的映射。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这一部分仍然可以查看&lt;a href=&quot;http://windrunnerlihuan.com/2017/03/12/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B8%80-Android%E5%9B%BE%E5%BD%A2%E6%98%BE%E7%A4%BA%E4%B9%8BHAL%E5%B1%82Gralloc%E6%A8%A1%E5%9D%97%E5%AE%9E%E7%8E%B0/&quot;&gt;Android SurfaceFlinger 学习之路(一)—-Android图形显示之HAL层Gralloc模块实现&lt;/a&gt;。我们仍然回顾一下以前的内容：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;registerBuffer和unregisterBuffer分别用来注册和注销一个指定的图形缓冲区，所谓注册图形缓冲区，实际上就是将一块图形缓冲区映射到一个进程的地址空间去，而注销图形缓冲区就是执行相反的操作。lock和unlock分别用来锁定和解锁一个指定的图形缓冲区，在访问一块图形缓冲区的时候，例如，向一块图形缓冲写入内容的时候，需要将该图形缓冲区锁定，用来避免访问冲突。在锁定一块图形缓冲区的时候，可以指定要锁定的图形绘冲区的位置以及大小，这是通过参数l、t、w和h来指定的，其中，参数l和t指定的是要访问的图形缓冲区的左上角位置，而参数w和h指定的是要访问的图形缓冲区的宽度和长度。锁定之后，就可以获得由参数参数l、t、w和h所圈定的一块缓冲区的起始地址，保存在输出参数vaddr中。另一方面，在访问完成一块图形缓冲区之后，需要解除这块图形缓冲区的锁定。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这就是内存缓冲区映射到应用进程的过程。因为需要映射共享内存，所以必须要序列化和反序列Pracel对象。如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%B8%83%29----%E5%88%9B%E5%BB%BA%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BAGraphicBuffer/unflatten.jpg&quot; alt=&quot;unflatten&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里我们创建GraphicBuffer流程就分析完了。&lt;/p&gt;
&lt;h1 id=&quot;小结&quot;&gt;&lt;a href=&quot;#小结&quot; class=&quot;headerlink&quot; title=&quot;小结&quot;&gt;&lt;/a&gt;小结&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;本节主要分析GraphicBuffer的创建过程，下一节我们分析对它的管理流程。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%B8%83%29----%E5%88%9B%E5%BB%BA%E5%9B%BE%E5%BD%A2%E7%BC%93%E5%86%B2%E5%8C%BAGraphicBuffer/meizi.png&quot; alt=&quot;meizi&quot;&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在上一篇SurfaceFlinger创建Surface流程中，我们会关联到BufferQueue对GraphicBuffer的管理机制，我们这次就来分析一下它的原理。&lt;br&gt;
    
    </summary>
    
      <category term="Android技术点" scheme="http://windrunnerlihuan.com/categories/Android%E6%8A%80%E6%9C%AF%E7%82%B9/"/>
    
    
      <category term="SurfaceFlinger" scheme="http://windrunnerlihuan.com/tags/SurfaceFlinger/"/>
    
  </entry>
  
  <entry>
    <title>Android SurfaceFlinger 学习之路(六)----SurfaceFlinger创建Surface</title>
    <link href="http://windrunnerlihuan.com/2017/06/17/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%85%AD-SurfaceFlinger%E5%88%9B%E5%BB%BASurface/"/>
    <id>http://windrunnerlihuan.com/2017/06/17/Android-SurfaceFlinger-学习之路-六-SurfaceFlinger创建Surface/</id>
    <published>2017-06-17T11:57:29.000Z</published>
    <updated>2019-01-06T07:29:16.358Z</updated>
    
    <content type="html">&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这次需要了解一下SurfaceFlinger创建Surface的流程，可能比较短，因为后面GraphicBuffer管理&lt;strong&gt;可能&lt;/strong&gt;会比较多。另外，应用层创建Surface以后会继续学习，并且流畅会比较长，因为设计到了WMS等等。&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%85%AD%29----SurfaceFlinger%E5%88%9B%E5%BB%BASurface/life.jpg&quot; alt=&quot;life&quot;&gt;&lt;/p&gt;
&lt;h1 id=&quot;图层分析&quot;&gt;&lt;a href=&quot;#图层分析&quot; class=&quot;headerlink&quot; title=&quot;图层分析&quot;&gt;&lt;/a&gt;图层分析&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在分析Android应用程序请求SurfaceFlinger创建Surface之前，我们首先了解一下Surface是由什么组成的。&lt;strong&gt;我们可以将Surface理解为一个绘图表面，Android应用程序负责往这个绘图表面上填内容，而SurfaceFlinger服务负责将这个绘图表面的内容取出来，并且渲染在显示屏上&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id=&quot;猜测&quot;&gt;&lt;a href=&quot;#猜测&quot; class=&quot;headerlink&quot; title=&quot;猜测&quot;&gt;&lt;/a&gt;猜测&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;每个应用程序对应着一个或者多个图形界面，而每一个界面我们称之为surface，或者说是window，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%85%AD%29----SurfaceFlinger%E5%88%9B%E5%BB%BASurface/surface.jpg&quot; alt=&quot;surface&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上图我们可以看到三个surface，在这里我们需要弄明白的问题是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;每个surface在屏幕上有它的位置、大小，然后每个surface 里面还有要显示的内容，内容、大小、位置 这些元素，在我们改变应用程序的时候都可能会改变，改变时应该如何处理？&lt;/li&gt;
&lt;li&gt;然后就各个surface 之间可能有重叠，比如说在上面的简略图中，灰色覆盖了橙色，绿色覆盖了橙色 ，而且还具有一定透明度。这种层之间的关系应该如何描述？&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;对于第一个问题，我们需要一个结构来记录应用程序界面的位置，大小，以及一个buffer 来记录需要显示的内容，所以这就是我们surface 的概念，surface 实际我们可以把它理解成一个容器，这个容器记录着应用程序界面的控制信息，比如说大小啊，位置啊，而它还有buffer 来专门存储需要显示的内容。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;对于第二个问题，我们可以想象在屏幕平面的垂直方向还有一个Z 轴，所有的surface 根据在Z 轴上的坐标来确定前后，这样就可以描述各个surface 之间的上下覆盖关系了，而这个在Z 轴上的顺序，图形上有个专业术语叫&lt;strong&gt;Z-order&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在这里还存在一个问题，那就是当存在图形重合的时候应该如何处理呢，而且可能有些surface 还带有透明信息，这里就是我们SurfaceFlinger 需要解决问题，它要把各个surface 组合(compose/merge) 成一个main Surface ，最后将Main Surface 的内容发送给FB，这样屏幕上就能看到我们想要的效果。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%85%AD%29----SurfaceFlinger%E5%88%9B%E5%BB%BASurface/composition.png&quot; alt=&quot;compositon&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;概述&quot;&gt;&lt;a href=&quot;#概述&quot; class=&quot;headerlink&quot; title=&quot;概述&quot;&gt;&lt;/a&gt;概述&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在Android中，Window与&lt;strong&gt;Surface&lt;/strong&gt;一一对应。 如果说Window关心的是层次和布局，是从设计者角度定义的类，Surface则从实现角度出发，是工程师关系和考虑的类。Window的内容是变化 的，Surface需要有空间来记录每个时刻Window的内容。在Android的SurfaceFlinger实现里，通常一个Surface有两块 Buffer, 一块用于绘画，一块用于显示，两个Buffer按照固定的频率进行交换，从而实现Window的动态刷新。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;但是，&lt;strong&gt;在SurfaceFlinger服务这一侧，绘图表面使用Layer类来描述&lt;/strong&gt;。&lt;strong&gt;Layer&lt;/strong&gt;是SurfaceFlinger 进行合成的基本操作单元。Layer在应用请求创建Surface的时候在SurfaceFlinger内部创建，因此一个Surface对应一个 Layer, 但注意，Surface不一定对应于Window，Android中有些Surface并不跟某个Window相关，而是有程序直接创建，比如说 StrictMode， 一块红色的背景，用于提示示Java代码中的一些异常, 还有SurfaceView, 用于显示有硬件输出的视频内容等。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Each Layer has：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Z order&lt;/li&gt;
&lt;li&gt;Alpha value from 0 to 255&lt;/li&gt;
&lt;li&gt;visibleRegion&lt;/li&gt;
&lt;li&gt;crop region&lt;/li&gt;
&lt;li&gt;transformation: rotate 0, 90, 180, 270: flip H, V: scale&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当多个Layer进行合成的时候，并不是整个Layer的空间都会被完全显示，根据这个Layer最终的显示效果，一个Layer可以被划分成很多的Region, Android SurfaceFlinger 定义了以下一些Region类型：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;TransparantRegion： 完全透明的区域，在它之下的区域将被显示出来。&lt;/li&gt;
&lt;li&gt;OpaqueRegion: 完全不透明的区域，是否显示取决于它上面是否有遮挡或是否透明。&lt;/li&gt;
&lt;li&gt;VisibleRegion: 可见区域，包括完全不透明无遮挡区域或半透明区域。 visibleRegion = Region - above OpaqueRegion.&lt;/li&gt;
&lt;li&gt;CoveredRegion: 被遮挡区域，在它之上，有不透明或半透明区域。&lt;/li&gt;
&lt;li&gt;DirtyRegion: 可见部分改变区域，包括新的被遮挡区域，和新的露出区域。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Android 系统支持多种显示设备，比如说，输出到手机屏幕，或者通过WiFi 投射到电视屏幕。Android用DisplayDevice类来表示这样的设备。不是所有的Layer都会输出到所有的Display, 比如说，我们可以只将Video Layer投射到电视， 而非整个屏幕。&lt;strong&gt;LayerStack&lt;/strong&gt; 就是为此设计，LayerStack 是一个Display 对象的一个数值， 而类Layer里成员State结构体也有成员变量mLayerStack， 只有两者的mLayerStack 值相同，Layer才会被输出到给该Display设备。所以LayerStack 决定了每个Display设备上可以显示的Layer数目。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceFlinger的工作内容，就是定期检查所有Layer的参数更新（LayerStack等），计算新的DirtyRegion，然后将结果推送给底层显示驱动进行显示。这里面有很多的细节，我们将在后续会专门研究。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面描述的几个概念，均是针对于显示这个层面，更多是涉及到中下层模块，应用层并不参与也无需关心。对于应用而言，它关心的是如何将内容画出来。Canvas 是Java层定义的一个类，它对应与Surface上的某个区域并提供了很多的2D绘制函数（借助于底层的Skia或OpenGL)。应用只需通过 LockCanvas() 来获取一个Canvas对象，并调用它的绘画方法，然后 unLockCanvasAndPost（）来通知底层将更新内容进行显示。当然，并不是所有应用程序都需要直接操作Canva， 事实上只有少量应用需要直接操作Canvas, Android提供了很多封装好的控件 Widget，应用只需提供素材，如文字，图片，属性等等，这些控件会调用Canvas提供的接口帮用户完成绘制工作。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceFlinger 是一个独立的Service， 它接收所有Window的Surface作为输入，根据Z-Order， 透明度，大小，位置等参数，计算出每个Surface在最终合成图像中的位置，然后交由HWComposer或OpenGL生成最终的显示Buffer, 然后显示到特定的显示设备上。&lt;/p&gt;
&lt;h1 id=&quot;Surface创建流程&quot;&gt;&lt;a href=&quot;#Surface创建流程&quot; class=&quot;headerlink&quot; title=&quot;Surface创建流程&quot;&gt;&lt;/a&gt;Surface创建流程&lt;/h1&gt;&lt;h2 id=&quot;SurfaceFlinger服务侧Layer创建&quot;&gt;&lt;a href=&quot;#SurfaceFlinger服务侧Layer创建&quot; class=&quot;headerlink&quot; title=&quot;SurfaceFlinger服务侧Layer创建&quot;&gt;&lt;/a&gt;SurfaceFlinger服务侧Layer创建&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面我们提，&lt;strong&gt;到在SurfaceFlinger服务这一侧，绘图表面使用Layer类来描述&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%85%AD%29----SurfaceFlinger%E5%88%9B%E5%BB%BASurface/layeruml.jpg&quot; alt=&quot;Layer&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Layer类内部定义了两个结构体Geometry、State，位于frameworks/native/services/surfaceflinger/Layer.h中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; Geometry &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; w;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; h;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Rect crop;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;inline&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt; ==(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Geometry&amp;amp; rhs) &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; (w == rhs.w &amp;amp;&amp;amp; h == rhs.h &amp;amp;&amp;amp; crop == rhs.crop);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;inline&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt; !=(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Geometry&amp;amp; rhs) &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; !&lt;span class=&quot;keyword&quot;&gt;operator&lt;/span&gt; ==(rhs);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; State &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Geometry active;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Geometry requested;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; z;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; layerStack;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint8_t&lt;/span&gt; alpha;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint8_t&lt;/span&gt; flags;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint8_t&lt;/span&gt; reserved[&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; sequence; &lt;span class=&quot;comment&quot;&gt;// changes when visible regions can change&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Transform transform;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// the transparentRegion hint is a bit special, it&#39;s latched only&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// when we receive a buffer -- this is because it&#39;s &quot;content&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// dependent.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Region activeTransparentRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Region requestedTransparentRegion;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;用变量mCurrentState和mDrawingState连个类型为State的成员变量保存当前和上一次的绘制状态，记录大小、可视区域、透明度、标志位、z-order等信息。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们可以回顾一下以前 &lt;a href=&quot;http://windrunnerlihuan.com/2017/05/02/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B8%89-Android%E5%BC%80%E6%9C%BA%E5%8A%A8%E7%94%BB%E6%B5%81%E7%A8%8B%E7%AE%80%E8%BF%B0/&quot;&gt;Android SurfaceFlinger 学习之路(三)—-Android开机动画流程简述&lt;/a&gt; ，开机动画中创建surface流程位于BootAnimation.cpp的readyToRun函数，位于frameworks/base/cmds/bootanimation/BootAnimation.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; BootAnimation::readyToRun() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// create the native surface&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;SurfaceControl&amp;gt; control = session()-&amp;gt;createSurface(String8(&lt;span class=&quot;string&quot;&gt;&quot;BootAnimation&quot;&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    SurfaceComposerClient::openGlobalTransaction();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    control-&amp;gt;setLayer(&lt;span class=&quot;number&quot;&gt;0x40000000&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    SurfaceComposerClient::closeGlobalTransaction();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;Surface&amp;gt; s = control-&amp;gt;getSurface();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;sp&amp;lt;SurfaceComposerClient&amp;gt; BootAnimation::session() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mSession;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;BootAnimation::BootAnimation() : Thread(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;), mZip(&lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSession = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; SurfaceComposerClient();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里session函数返回一个SurfaceComposerClient对象，在&lt;a href=&quot;http://windrunnerlihuan.com/2017/05/13/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%9B%9B-SurfaceFlinger%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%90%AF%E5%8A%A8%E4%B8%8E%E8%BF%9E%E6%8E%A5%E8%BF%87%E7%A8%8B/&quot;&gt;Android SurfaceFlinger 学习之路(四)—-SurfaceFlinger服务的启动与连接过程&lt;/a&gt;一文中，我们已经看到过SurfaceComposerClient类的作用了，Android应用程序主要就是通过它来和SurfaceFlinger服务建立连接的，连接的结果就是得到一个类型为Client的Binder代理对象，保存它的成员变量mClient中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们查看SurfaceComposerClient的createSurface函数，位于frameworks/native/libs/gui/SurfaceComposerClient.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sp&amp;lt;SurfaceControl&amp;gt; SurfaceComposerClient::createSurface(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; String8&amp;amp; name,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; w,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; h,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PixelFormat format,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;SurfaceControl&amp;gt; sur;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mStatus == NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;IBinder&amp;gt; handle;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;IGraphicBufferProducer&amp;gt; gbp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//我们先分析这里，里面有创建Layer的部分&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = mClient-&amp;gt;createSurface(name, w, h, format, flags,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;amp;handle, &amp;amp;gbp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE_IF(err, &lt;span class=&quot;string&quot;&gt;&quot;SurfaceComposerClient::createSurface error %s&quot;&lt;/span&gt;, strerror(-err));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sur = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; SurfaceControl(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;, handle, gbp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; sur;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;因此又要到Client的createSurface函数中，位于frameworks/native/services/surfaceflinger/Client.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; Client::createSurface(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; String8&amp;amp; name,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; h, PixelFormat format, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;IBinder&amp;gt;* handle,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;IGraphicBufferProducer&amp;gt;* gbp)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * createSurface must be called from the GL thread so that it can&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * have access to the GL context.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; MessageCreateLayer : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; MessageBase &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        SurfaceFlinger* flinger;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Client* client;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;IBinder&amp;gt;* handle;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;IGraphicBufferProducer&amp;gt;* gbp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; result;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; String8&amp;amp; name;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; w, h;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PixelFormat format;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        MessageCreateLayer(SurfaceFlinger* flinger,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; String8&amp;amp; name, Client* client,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; h, PixelFormat format, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                sp&amp;lt;IBinder&amp;gt;* handle,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                sp&amp;lt;IGraphicBufferProducer&amp;gt;* gbp)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            : flinger(flinger), client(client),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              handle(handle), gbp(gbp),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              name(name), w(w), h(h), format(format), flags(flags) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; getResult() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123; &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; result; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//给SurfaceFlinger的MessageQueue发送同步消息，createLayer函数被调用&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            result = flinger-&amp;gt;createLayer(name, client, w, h, format, flags,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    handle, gbp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;MessageBase&amp;gt; msg = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; MessageCreateLayer(mFlinger.get(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            name, &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;, w, h, format, flags, handle, gbp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFlinger-&amp;gt;postMessageSync(msg);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;MessageCreateLayer*&amp;gt;( msg.get() )-&amp;gt;getResult();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;给SurfaceFlinger的MessageQueue发送同步消息，createLayer函数被调用，位于frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; SurfaceFlinger::createLayer(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; String8&amp;amp; name,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;Client&amp;gt;&amp;amp; client,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; h, PixelFormat format, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;IBinder&amp;gt;* handle, sp&amp;lt;IGraphicBufferProducer&amp;gt;* gbp)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//ALOGD(&quot;createLayer for (%d x %d), name=%s&quot;, w, h, name.string());&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt;(w|h) &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;createLayer() failed, w or h is negative (w=%d, h=%d)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;(w), &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;(h));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; BAD_VALUE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; result = NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;Layer&amp;gt; layer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt; (flags &amp;amp; ISurfaceComposerClient::eFXSurfaceMask) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; ISurfaceComposerClient::eFXSurfaceNormal:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//创建普通的Layer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            result = createNormalLayer(client,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    name, w, h, flags, format,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    handle, gbp, &amp;amp;layer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; ISurfaceComposerClient::eFXSurfaceDim:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;////创建模糊的Layer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            result = createDimLayer(client,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    name, w, h, flags,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    handle, gbp, &amp;amp;layer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;default&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            result = BAD_VALUE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (result == NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//将创建的Layer按顺序添加进list中，我们以后讲z-order会讲&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        addClientLayer(client, *handle, *gbp, layer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//修改标志位&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        setTransactionFlags(eTransactionNeeded);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; result;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里会根据传进来的flag判断创建什么类型的Layer，一个是普通的，一个是模糊的Layer。这里我们只看看普通的Layer，createNormalLayer函数。&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; SurfaceFlinger::createNormalLayer(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;Client&amp;gt;&amp;amp; client,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; String8&amp;amp; name, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; h, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags, PixelFormat&amp;amp; format,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;IBinder&amp;gt;* handle, sp&amp;lt;IGraphicBufferProducer&amp;gt;* gbp, sp&amp;lt;Layer&amp;gt;* outLayer)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// initialize the surfaces&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt; (format) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//像素格式&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; PIXEL_FORMAT_TRANSPARENT:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; PIXEL_FORMAT_TRANSLUCENT:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        format = PIXEL_FORMAT_RGBA_8888;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; PIXEL_FORMAT_OPAQUE:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        format = PIXEL_FORMAT_RGBX_8888;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//创建一个Layer对象&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    *outLayer = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Layer(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;, client, name, w, h, flags);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//调用Layer的setBuffers函数，这只一些变量&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = (*outLayer)-&amp;gt;setBuffers(w, h, format, flags);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//给成员变量handle和gbp赋值&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        *handle = (*outLayer)-&amp;gt;getHandle();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        *gbp = (*outLayer)-&amp;gt;getProducer();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGE_IF(err, &lt;span class=&quot;string&quot;&gt;&quot;createNormalLayer() failed (%s)&quot;&lt;/span&gt;, strerror(-err));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里创建了一个Layer对象，我们可以看看Layer的构造函数，位于frameworks/native/services/surfaceflinger/Layer.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;Layer::Layer(SurfaceFlinger* flinger, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;Client&amp;gt;&amp;amp; client,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; String8&amp;amp; name, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; h, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    :   contentDirty(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sequence(&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;(android_atomic_inc(&amp;amp;sSequence))),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mFlinger(flinger),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mTextureName(&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;U),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mPremultipliedAlpha(&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mName(&lt;span class=&quot;string&quot;&gt;&quot;unnamed&quot;&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mDebug(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mFormat(PIXEL_FORMAT_NONE),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mTransactionFlags(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mQueuedFrames(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSidebandStreamChanged(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mCurrentTransform(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mCurrentOpacity(&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mRefreshPending(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mFrameLatencyNeeded(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mFiltering(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mNeedsFiltering(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mMesh(Mesh::TRIANGLE_FAN, &lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSecure(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mProtectedByApp(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mHasSurface(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mClientRef(client),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mPotentialCursor(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentCrop.makeInvalid();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFlinger-&amp;gt;getRenderEngine().genTextures(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &amp;amp;mTextureName);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; layerFlags = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (flags &amp;amp; ISurfaceComposerClient::eHidden)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        layerFlags |= &lt;span class=&quot;keyword&quot;&gt;layer_state_t&lt;/span&gt;::eLayerHidden;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (flags &amp;amp; ISurfaceComposerClient::eOpaque)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        layerFlags |= &lt;span class=&quot;keyword&quot;&gt;layer_state_t&lt;/span&gt;::eLayerOpaque;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (flags &amp;amp; ISurfaceComposerClient::eNonPremultiplied)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mPremultipliedAlpha = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mName = name;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentState.active.w = w;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentState.active.h = h;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentState.active.crop.makeInvalid();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentState.z = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentState.alpha = &lt;span class=&quot;number&quot;&gt;0xFF&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentState.layerStack = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentState.flags = layerFlags;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentState.sequence = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentState.transform.&lt;span class=&quot;built_in&quot;&gt;set&lt;/span&gt;(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentState.requested = mCurrentState.active;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// drawing state &amp;amp; current state are identical&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDrawingState = mCurrentState;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; displayPeriod =&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            flinger-&amp;gt;getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFrameTracker.setDisplayRefreshPeriod(displayPeriod);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Layer的构造函数中就是给一些变量赋了初值，事情不多。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们从上面的类图看到Layer间接继承于RefBase类，所以对象第一次被赋值给强指针会调用onFirstRef函数，我们看看它里面做了那些事情：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; Layer::onFirstRef() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Creates a custom BufferQueue for SurfaceFlingerConsumer to use&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;IGraphicBufferProducer&amp;gt; producer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;IGraphicBufferConsumer&amp;gt; consumer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//BufferQueue创建图形缓冲区管理成员，我们以后分析图形缓冲区管理会讲到&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BufferQueue::createBufferQueue(&amp;amp;producer, &amp;amp;consumer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//mProducer 不为空了，赋值&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mProducer = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; MonitoredProducer(producer, mFlinger);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//mSurfaceFlingerConsumer 不为空了，赋值&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; SurfaceFlingerConsumer(consumer, mTextureName);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//设置消费者相关设置&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer-&amp;gt;setConsumerUsageBits(getEffectiveUsage(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer-&amp;gt;setContentsChangedListener(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer-&amp;gt;setName(mName);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// TARGET_DISABLE_TRIPLE_BUFFERING为false，所以使用了三缓冲，project butter计划嘛&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;ifdef&lt;/span&gt; TARGET_DISABLE_TRIPLE_BUFFERING&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;warning&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&quot;disabling triple buffering&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer-&amp;gt;setDefaultMaxBufferCount(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;else&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer-&amp;gt;setDefaultMaxBufferCount(&lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//获取默认显示器&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; DisplayDevice&amp;gt; hw(mFlinger-&amp;gt;getDefaultDisplayDevice());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//更新显示图像方向&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    updateTransformHint(hw);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;onFirstRef函数中做的事情主要是创建图形缓冲区管理成员相关，这个我们后面会讲到。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后就是根据“黄油计划”定义了三缓冲，以及显示器方向的调整。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Layer对象创建完后，就调用Layer的setBuffers函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; Layer::setBuffers( &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; h,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            PixelFormat format, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; maxSurfaceDims = min(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mFlinger-&amp;gt;getMaxTextureSize(), mFlinger-&amp;gt;getMaxViewportDims());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// never allow a surface larger than what our underlying GL implementation&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// can handle.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;(w)&amp;gt;maxSurfaceDims) || (&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;(h)&amp;gt;maxSurfaceDims)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;dimensions too large %u x %u&quot;&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;(w), &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;(h));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; BAD_VALUE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFormat = format;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mPotentialCursor = (flags &amp;amp; ISurfaceComposerClient::eCursorWindow) ? &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt; : &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSecure = (flags &amp;amp; ISurfaceComposerClient::eSecure) ? &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt; : &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mProtectedByApp = (flags &amp;amp; ISurfaceComposerClient::eProtectedByApp) ? &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt; : &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentOpacity = getOpacityForFormat(format);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer-&amp;gt;setDefaultBufferSize(w, h);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer-&amp;gt;setDefaultBufferFormat(format);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurfaceFlingerConsumer-&amp;gt;setConsumerUsageBits(getEffectiveUsage(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里也是一些变量的设置，东西不多。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后就是给gbp和handle赋值。gbp已经不为空了，我们在onFirstRef函数中对它付了值。那么我们看看给handle赋值，Layer的getHandle函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sp&amp;lt;IBinder&amp;gt; Layer::getHandle() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::Autolock _l(mLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    LOG_ALWAYS_FATAL_IF(mHasSurface,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;string&quot;&gt;&quot;Layer::getHandle() has already been called&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mHasSurface = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * The layer handle is just a BBinder object passed to the client&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * (remote process) -- we don&#39;t keep any reference on our side such that&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * the dtor is called when the remote side let go of its reference.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     *&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * LayerCleaner ensures that mFlinger-&amp;gt;onLayerDestroyed() is called for&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * this layer when the handle is destroyed.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; Handle : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; BBinder, &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; LayerCleaner &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        wp&amp;lt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Layer&amp;gt; mOwner;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Handle(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;SurfaceFlinger&amp;gt;&amp;amp; flinger, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;Layer&amp;gt;&amp;amp; layer)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            : LayerCleaner(flinger, layer), mOwner(layer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Handle(mFlinger, &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;只是新建一个Handle，而这个Handle只是一个Binder的实现，就是标识Surface的全局唯一性，没有什么实际的内容。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上述就是Layer的创建，是基于SurfaceFlinger服务端这一侧。&lt;/p&gt;
&lt;h2 id=&quot;应用侧Surface创建&quot;&gt;&lt;a href=&quot;#应用侧Surface创建&quot; class=&quot;headerlink&quot; title=&quot;应用侧Surface创建&quot;&gt;&lt;/a&gt;应用侧Surface创建&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们继续回到上面的SurfaceComposerClient的createSurface函数，为了不往上翻我再贴一遍：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sp&amp;lt;SurfaceControl&amp;gt; SurfaceComposerClient::createSurface(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; String8&amp;amp; name,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; w,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; h,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PixelFormat format,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;SurfaceControl&amp;gt; sur;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mStatus == NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;IBinder&amp;gt; handle;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;IGraphicBufferProducer&amp;gt; gbp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//上面分析完了SurfaceFlinger创建完了一个Layer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = mClient-&amp;gt;createSurface(name, w, h, format, flags,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;amp;handle, &amp;amp;gbp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE_IF(err, &lt;span class=&quot;string&quot;&gt;&quot;SurfaceComposerClient::createSurface error %s&quot;&lt;/span&gt;, strerror(-err));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//根据上面创建Layer时创建的handle和gbp再创建一个SurfaceControl，并返回&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sur = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; SurfaceControl(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;, handle, gbp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; sur;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面分析完了SurfaceFlinger创建完了一个Layer，接着根据上面创建Layer时创建的handle和gbp再创建一个SurfaceControl，并返回。&lt;/p&gt;
&lt;h3 id=&quot;SurfaceControl创建&quot;&gt;&lt;a href=&quot;#SurfaceControl创建&quot; class=&quot;headerlink&quot; title=&quot;SurfaceControl创建&quot;&gt;&lt;/a&gt;SurfaceControl创建&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;在Android应用程序这一侧，每一个绘图表面都使用一个Surface对象来描述&lt;/strong&gt;，每一个Surface对象都是由一个SurfaceControl对象来创建的。Surface类和SurfaceControl类的关系以及实现如图所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%85%AD%29----SurfaceFlinger%E5%88%9B%E5%BB%BASurface/SurfaceControl.jpg&quot; alt=&quot;SurfaceControl&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceControl类的成员变量mClient是一个类型为SurfaceComposerClient对象，在&lt;a href=&quot;http://windrunnerlihuan.com/2017/05/13/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%9B%9B-SurfaceFlinger%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%90%AF%E5%8A%A8%E4%B8%8E%E8%BF%9E%E6%8E%A5%E8%BF%87%E7%A8%8B/&quot;&gt;Android SurfaceFlinger 学习之路(四)—-SurfaceFlinger服务的启动与连接过程&lt;/a&gt;一文中，我们已经看到过SurfaceComposerClient类的作用了，Android应用程序主要就是通过它来和SurfaceFlinger服务建立连接的，连接的结果就是得到一个类型为Client的Binder代理对象，保存它的成员变量mClient中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceControl类的成员变量mHandle是指向的就是我们上面分析的创建Layer时，最后将Layer和SurfaceFlinger作为构造函数的参数创建一个Handle对象，这个Handle是一个Binder的实现，就是标识Surface的全局唯一性。当Android应用程序请求SurfaceFlinger服务创建一个绘图表面的时候，SurfaceFlinger服务就会在内部创建一个Layer对象，然后将Layer和SurfaceFlinger包装成一个Handle的一个Binder代理对象返回来给Android应用程序，然后Android应用程序再将这个Binder代理对象保存在一个SurfaceControl对象的成员变量mHandle中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceControl类的成员变量mSurfaceData是一个类型为Surface的强指针，它指向了一个Surface对象。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceControl的构造函数也比较简单，位于frameworks/native/libs/gui/SurfaceControl.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;SurfaceControl::SurfaceControl(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;SurfaceComposerClient&amp;gt;&amp;amp; client,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;IBinder&amp;gt;&amp;amp; handle,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;IGraphicBufferProducer&amp;gt;&amp;amp; gbp)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    : mClient(client), mHandle(handle), mGraphicBufferProducer(gbp)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceControl类创建就到这里。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;附：&lt;/strong&gt;这是native层的SurfaceControl，对于java层，也有一个SurfaceControl，Android 4.3 里新引进的类。Google从之前的Surface类里拆出部分接口，变成SurfaceControl，为什么要这样？为了让结构更清晰，WindowManagerService 只能对Surface进行控制，但并不更新Surface里的内容，分拆之后，WindowManagerService 只能访问SurfaceControl，它主要控制Surface的创建，销毁，Z-order，透明度，显示或隐藏，等等。而真正的更新者，View会通过Canvas的接口将内容画到Surface上。那View怎么拿到WMService创建的Surface，答案是outSurface.copyFrom(surfaceControl)；，surfaceControl 被转换成一个Surface对象，然后传回给ViewRoot, 前面创建的空的Surface现在有了实质内容。Surface通过这种方式被创建出来，Surface对应的Buffer 也相应的在SurfaceFlinger内部通过HAL层模块（GRAlloc)分配并维护在SurfaceFlinger 内部，Canvas() 通过dequeueBuffer（）接口拿到Surface的一个Buffer，绘制完成后通过queueBuffer（）还给SurfaceFlinger进行绘制。（&lt;strong&gt;这一部分我们后期学习WMS时候再分析&lt;/strong&gt;）&lt;/p&gt;
&lt;h3 id=&quot;Surface创建&quot;&gt;&lt;a href=&quot;#Surface创建&quot; class=&quot;headerlink&quot; title=&quot;Surface创建&quot;&gt;&lt;/a&gt;Surface创建&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从上面的类图，可以看到Surface类的成员变量mGraphicBufferProducer指向一个sp&amp;lt; IGraphicBufferProducer &amp;gt; 类型的对象，在Layer的onFirstRef函数中，mProducer复制后，类型为MonitoredProducer，将它有传给了Surface中。我们注意MonitoredProducer构造函数的一个参数producer，事实上MonitoredProducer只是一个代理类，真正的实现在这个producer参数。它是在BufferQueue::createBufferQueue中创造的。这个我们下一篇会分析这个。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Surface类继承了ANativeObjectBase类，而ANativeObjectBase类又继承了ANativeWindow类。我们知道，Android系统是通过OpenGL库来绘制UI的。OpenGL库在绘制UI的时候，需要底层的系统提供一个本地窗口给它，以便它可以将UI绘制在这个本地窗口上。Android系统为OpenGL库定提供的本地窗口使用ANativeWindow类来描述，Surface类通过ANativeObjectBase类间接地继承了ANativeWindow类，因此，Surface类也是用来描述OpenGL绘图所需要的一个本地窗口的。从这个角度出发，我们可以将Surface类看作OpenGL库与Android的UI系统之间的一个桥梁。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;创建Surface的函数也很简单，查看SurfaceControl的getSurface函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sp&amp;lt;Surface&amp;gt; SurfaceControl::getSurface() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::Autolock _l(mLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mSurfaceData == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// This surface is always consumed by SurfaceFlinger, so the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// producerControlledByApp value doesn&#39;t matter; using false.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSurfaceData = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Surface(mGraphicBufferProducer, &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mSurfaceData;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;以及看看Surface的构造函数，位于frameworks/native/libs/gui/Surface.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;Surface::Surface(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;IGraphicBufferProducer&amp;gt;&amp;amp; bufferProducer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; controlledByApp)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    : mGraphicBufferProducer(bufferProducer)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Initialize the ANativeWindow function pointers.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ANativeWindow::setSwapInterval  = hook_setSwapInterval;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ANativeWindow::dequeueBuffer    = hook_dequeueBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ANativeWindow::cancelBuffer     = hook_cancelBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ANativeWindow::queueBuffer      = hook_queueBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ANativeWindow::query            = hook_query;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ANativeWindow::perform          = hook_perform;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ANativeWindow::cancelBuffer_DEPRECATED  = hook_cancelBuffer_DEPRECATED;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ANativeWindow::lockBuffer_DEPRECATED    = hook_lockBuffer_DEPRECATED;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ANativeWindow::queueBuffer_DEPRECATED   = hook_queueBuffer_DEPRECATED;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;&amp;amp;&amp;gt;(ANativeWindow::minSwapInterval) = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;&amp;amp;&amp;gt;(ANativeWindow::maxSwapInterval) = &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mReqWidth = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mReqHeight = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mReqFormat = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mReqUsage = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCrop.clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mTransform = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mStickyTransform = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDefaultWidth = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDefaultHeight = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mUserWidth = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mUserHeight = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mTransformHint = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mConsumerRunningBehind = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mConnectedToCpu = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mProducerControlledByApp = controlledByApp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSwapIntervalZero = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;主要是设置了一些钩子方法，用于创建GraphicBuffer等等。还有一些变量的初始化。所以重点应该在这些钩子方法当中，我们下一节会分析。&lt;/p&gt;
&lt;h1 id=&quot;小结&quot;&gt;&lt;a href=&quot;#小结&quot; class=&quot;headerlink&quot; title=&quot;小结&quot;&gt;&lt;/a&gt;小结&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;本节我们主要讲了SurfaceFlinger创建Surface的过程，文章末尾我们我发现管理图形缓冲区的一个重要工具：BufferQueue。我们下一节会分析这个。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%85%AD%29----SurfaceFlinger%E5%88%9B%E5%BB%BASurface/meizi.jpg&quot; alt=&quot;meizi&quot;&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这次需要了解一下SurfaceFlinger创建Surface的流程，可能比较短，因为后面GraphicBuffer管理&lt;strong&gt;可能&lt;/strong&gt;会比较多。另外，应用层创建Surface以后会继续学习，并且流畅会比较长，因为设计到了WMS等等。&lt;br&gt;
    
    </summary>
    
      <category term="Android技术点" scheme="http://windrunnerlihuan.com/categories/Android%E6%8A%80%E6%9C%AF%E7%82%B9/"/>
    
    
      <category term="SurfaceFlinger" scheme="http://windrunnerlihuan.com/tags/SurfaceFlinger/"/>
    
  </entry>
  
  <entry>
    <title>Android SurfaceFlinger 学习之路(五)----VSync 工作原理</title>
    <link href="http://windrunnerlihuan.com/2017/05/25/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%BA%94-VSync-%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/"/>
    <id>http://windrunnerlihuan.com/2017/05/25/Android-SurfaceFlinger-学习之路-五-VSync-工作原理/</id>
    <published>2017-05-25T08:27:02.000Z</published>
    <updated>2019-01-06T07:28:58.846Z</updated>
    
    <content type="html">&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;VSync信号的科普我们上一篇已经介绍过了，这篇我们要分析在SurfaceFlinger中的作用。（愈发觉得做笔记对自己记忆模块巩固有很多帮助，整理文章不一定是用来给别人看的，但一定是为加强自己记忆的~）&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;流程基础&quot;&gt;&lt;a href=&quot;#流程基础&quot; class=&quot;headerlink&quot; title=&quot;流程基础&quot;&gt;&lt;/a&gt;流程基础&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从上一篇得知，Android 4.1一个很大的更新是Project Butter，黄油计划，为了解决用户交互体验差的问题(Jelly Bean is crazy fast)。Project Butter对Android Display系统进行了重构，引入了三个核心元素，即VSYNC、Triple Buffer和Choreographer。&lt;/p&gt;
&lt;h2 id=&quot;硬件加载&quot;&gt;&lt;a href=&quot;#硬件加载&quot; class=&quot;headerlink&quot; title=&quot;硬件加载&quot;&gt;&lt;/a&gt;硬件加载&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上上一节我们初略分析了SurfaceFlinger的启动流程，从SurfaceFlinger类的初始化流程得知，其init方法初始化了很多参数。我们分析Vsync流程需要这些信息，位于frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp中。&lt;/p&gt;
&lt;h3 id=&quot;显示设备&quot;&gt;&lt;a href=&quot;#显示设备&quot; class=&quot;headerlink&quot; title=&quot;显示设备&quot;&gt;&lt;/a&gt;显示设备&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceFlinger中需要显示的图层（layer）将通过DisplayDevice对象传递到OpenGLES中进行合成，合成之后的图像再通过HWComposer对象传递到Framebuffer中显示。DisplayDevice对象中的成员变量mVisibleLayersSortedByZ保存了所有需要显示在本显示设备中显示的Layer对象，同时DisplayDevice对象也保存了和显示设备相关的显示方向、显示区域坐标等信息。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;DisplayDevice是显示设备的抽象，定义了3中类型的显示设备。引用枚举类位于frameworks/native/services/surfaceflinger/DisplayDevice.h中，定义枚举位于hardware/libhardware/include/hardware/Hwcomposer_defs.h中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//DisplayDevice.h&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;enum&lt;/span&gt; DisplayType &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        DISPLAY_ID_INVALID = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        DISPLAY_PRIMARY     = HWC_DISPLAY_PRIMARY,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        DISPLAY_EXTERNAL    = HWC_DISPLAY_EXTERNAL,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        DISPLAY_VIRTUAL     = HWC_DISPLAY_VIRTUAL,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        NUM_BUILTIN_DISPLAY_TYPES = HWC_NUM_PHYSICAL_DISPLAY_TYPES,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//Hwcomposer_defs.h&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* Display types and associated mask bits. */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;enum&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    HWC_DISPLAY_PRIMARY     = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    HWC_DISPLAY_EXTERNAL    = &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;,    &lt;span class=&quot;comment&quot;&gt;// HDMI, DP, etc.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    HWC_DISPLAY_VIRTUAL     = &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    HWC_NUM_PHYSICAL_DISPLAY_TYPES = &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    HWC_NUM_DISPLAY_TYPES          = &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DISPLAY_PRIMARY：主显示设备，通常是LCD屏&lt;/li&gt;
&lt;li&gt;DISPLAY_EXTERNAL：扩展显示设备。通过HDMI输出的显示信号&lt;/li&gt;
&lt;li&gt;DISPLAY_VIRTUAL：虚拟显示设备，通过WIFI输出信号&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这三种设备，第一种就是我们手机、电视的主显示屏，另外两种需要硬件扩展。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;初始化显示设备模块位于SurfaceFlinger中的init函数：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;void SurfaceFlinger::init() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //初始化HWComposer硬件设备，我们下面会讲到&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // actual hardware composer underneath.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mHwc = new HWComposer(this,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            *static_cast&amp;lt;HWComposer::EventHandler *&amp;gt;(this));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //初始化物理显示设备&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // initialize our non-virtual displays&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //物理设备类型总数为2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    for (size_t i=0 ; i&amp;lt;DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // set-up the displays that are already connected&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //先调用了HWComposer的isConnected来检查显示设备是否已连接，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //只有和显示设备连接的DisplayDevice对象才会被创建出来。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //即使没有任何物理显示设备被检测到，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //SurfaceFlinger都需要一个DisplayDevice对象才能正常工作，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //因此，DISPLAY_PRIMARY类型的DisplayDevice对象总是会被创建出来。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (mHwc-&amp;gt;isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // All non-virtual displays are currently considered secure.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            bool isSecure = true;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ////给显示设备分配一个token,一般都是一个binder&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            createBuiltinDisplayLocked(type);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            wp&amp;lt;IBinder&amp;gt; token = mBuiltinDisplays[i];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //然后会调用createBufferQueue函数创建一个producer和consumer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sp&amp;lt;IGraphicBufferProducer&amp;gt; producer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sp&amp;lt;IGraphicBufferConsumer&amp;gt; consumer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            BufferQueue::createBufferQueue(&amp;amp;producer, &amp;amp;consumer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    new GraphicBufferAlloc());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //然后又创建了一个FramebufferSurface对象，把consumer参数传入代表是一个消费者。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sp&amp;lt;FramebufferSurface&amp;gt; fbs = new FramebufferSurface(*mHwc, i,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    consumer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            int32_t hwcId = allocateHwcDisplayId(type);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //创建DisplayDevice对象，代表一类显示设备&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sp&amp;lt;DisplayDevice&amp;gt; hw = new DisplayDevice(this,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    type, hwcId, mHwc-&amp;gt;getFormat(hwcId), isSecure, token,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    fbs, producer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    mRenderEngine-&amp;gt;getEGLConfig());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //如果不是主屏幕        &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (i &amp;gt; DisplayDevice::DISPLAY_PRIMARY) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // FIXME: currently we don&#39;t get blank/unblank requests&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // for displays other than the main display, so we always&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // assume a connected display is unblanked.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ALOGD(&quot;marking display %zu as acquired/unblanked&quot;, i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //通常我们不会在次屏幕获得熄灭/点亮LCD的请求，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //所以我们总是认为次显屏是点亮的&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //设置PowerMode为HWC_POWER_MODE_NORMAL&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                hw-&amp;gt;setPowerMode(HWC_POWER_MODE_NORMAL);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mDisplays.add(token, hw);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上述过程就是初始化显示设备，我们分部查看。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）检查设备连接：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所有显示设备的输出都要通过HWComposer对象完成，因此上面这段代码先调用了HWComposer的isConnected来检查显示设备是否已连接，只有和显示设备连接的DisplayDevice对象才会被创建出来。即使没有任何物理显示设备被检测到，SurfaceFlinger都需要一个DisplayDevice对象才能正常工作，因此，DISPLAY_PRIMARY类型的DisplayDevice对象总是会被创建出来。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;createBuiltinDisplayLocked函数就是为显示设备对象创建一个BBinder类型的Token：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::createBuiltinDisplayLocked(DisplayDevice::DisplayType type) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGW_IF(mBuiltinDisplays[type],&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;string&quot;&gt;&quot;Overwriting display token for display type %d&quot;&lt;/span&gt;, type);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//一般这种token之类的东西，都是一个binder&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mBuiltinDisplays[type] = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; BBinder();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;DisplayDeviceState &lt;span class=&quot;title&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(type)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// All non-virtual displays are currently considered secure.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    info.isSecure = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCurrentState.displays.add(mBuiltinDisplays[type], info);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;一般这种token之类的东西，都是一个binder，就像我们创建window需要一个token，也是new一个binder然后在WindowManagerService里注册。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）初始化GraphicBuffer相关内容：（这一部分我们后续分析GraphicBuffer管理相关会仔细分析它，这里只是粗略介绍）&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后会调用createBufferQueue函数创建一个producer和consumer。&lt;strong&gt;然后又创建了一个FramebufferSurface对象。这里我们看到在新建FramebufferSurface对象时把consumer参数传入了代表是一个消费者。&lt;/strong&gt;&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;而在DisplayDevice的构造函数中（下面会讲到），会创建一个Surface对象传递给底层的OpenGL ES使用，而这个Surface是一个生产者。在OpenGl ES中合成好了图像之后会将图像数据写到Surface对象中，这将触发consumer对象的onFrameAvailable函数被调用。&lt;/strong&gt;&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这就是Surface数据好了就通知消费者来拿数据做显示用，&lt;strong&gt;在onFrameAvailable函数汇总，通过nextBuffer获得图像数据，然后调用HWComposer对象mHwc的fbPost函数输出。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;FramebufferSurface类位于frameworks/native/services/surfaceflinger/displayhardware/FramebufferSurface.cpp中，我们查看它的的onFrameAvailable函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// Overrides ConsumerBase::onFrameAvailable(), does not call base class impl.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; FramebufferSurface::onFrameAvailable() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;GraphicBuffer&amp;gt; buf;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;Fence&amp;gt; acquireFence;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//通过nextBuffer获得图像数据&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = nextBuffer(buf, acquireFence);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;error latching nnext FramebufferSurface buffer: %s (%d)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                strerror(-err), err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//调用HWComposer的fbPost函数输出图像，fbPost函数最后通过调用Gralloc模块的post函数来输出图像&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    err = mHwc.fbPost(mDisplayType, acquireFence, buf);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;error posting framebuffer: %d&quot;&lt;/span&gt;, err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个流程我们下几节会仔细分析，这里我们粗略过个流程：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;通过nextBuffer获得图像数据；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后调用HWComposer对象mHwc的fbPost函数输出，fbPost函数最后通过调用Gralloc模块的post函数来输出图像。这一部分我们在&lt;a href=&quot;http://windrunnerlihuan.com/2017/03/12/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B8%80-Android%E5%9B%BE%E5%BD%A2%E6%98%BE%E7%A4%BA%E4%B9%8BHAL%E5%B1%82Gralloc%E6%A8%A1%E5%9D%97%E5%AE%9E%E7%8E%B0/&quot;&gt;Android SurfaceFlinger 学习之路(一)—-Android图形显示之HAL层Gralloc模块实现&lt;/a&gt;分析过了，可以查看这个链接。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）创建DisplayDevice对象，用来描述显示设备：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们再来看看DisplayDevice的构造函数，位于frameworks/native/services/surfaceflinger/DisplayDevice.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * Initialize the display to the specified values.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; *&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;DisplayDevice::DisplayDevice(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;SurfaceFlinger&amp;gt;&amp;amp; flinger,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        DisplayType type,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; hwcId,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; format,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; isSecure,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; wp&amp;lt;IBinder&amp;gt;&amp;amp; displayToken,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;DisplaySurface&amp;gt;&amp;amp; displaySurface,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;IGraphicBufferProducer&amp;gt;&amp;amp; producer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        EGLConfig config)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    : lastCompositionHadVisibleLayers(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mFlinger(flinger),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mType(type), mHwcDisplayId(hwcId),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mDisplayToken(displayToken),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mDisplaySurface(displaySurface),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mDisplay(EGL_NO_DISPLAY),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mSurface(EGL_NO_SURFACE),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mDisplayWidth(), mDisplayHeight(), mFormat(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mFlags(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mPageFlipCount(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mIsSecure(isSecure),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mSecureLayerVisible(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mLayerStack(NO_LAYER_STACK),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mOrientation(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mPowerMode(HWC_POWER_MODE_OFF),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mActiveConfig(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//创建surface，传递给底层的OpenGL ES使用，而这个Surface是一个生产者&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mNativeWindow = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Surface(producer, &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ANativeWindow* &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; window = mNativeWindow.get();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * Create our display&#39;s surface&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//在OpenGl ES中合成好了图像之后会将图像数据写到Surface对象中&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLSurface surface;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLint w, h;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (config == EGL_NO_CONFIG) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        config = RenderEngine::chooseEglConfig(display, format);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    surface = eglCreateWindowSurface(display, config, window, &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    eglQuerySurface(display, surface, EGL_WIDTH,  &amp;amp;mDisplayWidth);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    eglQuerySurface(display, surface, EGL_HEIGHT, &amp;amp;mDisplayHeight);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Make sure that composition can never be stalled by a virtual display&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// consumer that isn&#39;t processing buffers fast enough. We have to do this&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// in two places:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// * Here, in case the display is composed entirely by HWC.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//   window&#39;s swap interval in eglMakeCurrent, so they&#39;ll override the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//   interval we set here.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;////虚拟设备不支持图像合成  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mType &amp;gt;= DisplayDevice::DISPLAY_VIRTUAL)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        window-&amp;gt;setSwapInterval(window, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mConfig = config;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDisplay = display;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurface = surface;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFormat  = format;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mPageFlipCount = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mViewport.makeInvalid();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFrame.makeInvalid();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// virtual displays are always considered enabled&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//虚拟设备屏幕认为是不关闭的 &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mPowerMode = (mType &amp;gt;= DisplayDevice::DISPLAY_VIRTUAL) ?&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                  HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Name the display.  The name will be replaced shortly if the display&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// was created with createDisplay().&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//根据显示设备类型赋名称&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt; (mType) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; DISPLAY_PRIMARY:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mDisplayName = &lt;span class=&quot;string&quot;&gt;&quot;Built-in Screen&quot;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; DISPLAY_EXTERNAL:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mDisplayName = &lt;span class=&quot;string&quot;&gt;&quot;HDMI Screen&quot;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;default&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mDisplayName = &lt;span class=&quot;string&quot;&gt;&quot;Virtual Screen&quot;&lt;/span&gt;;    &lt;span class=&quot;comment&quot;&gt;// e.g. Overlay #n&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// initialize the display orientation transform.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//调整显示设备视角的大小、位移、旋转等参数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;DisplayDevice的构造函数初始化了一些参数，但是最重要的是：&lt;strong&gt;创建了一个Surface对象mNativeWindow，同时用它作为参数创建EGLSurface对象，这个EGLSurface对象是OpenGL ES中绘图需要的&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;这样，在DisplayDevice中就建立了一个通向Framebuffer的通道，只要向DisplayDevice的mSurface写入数据。就会到消费者FrameBufferSurface的onFrameAvailable函数，然后到HWComposer在到Gralloc模块，最后输出到显示设备。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;附（以后会讲到）：DisplayDevice有个函数swapBuffers。swapBuffers函数将内部缓冲区的图像数据刷新到显示设备的Framebuffer中，它通过调用eglSwapBuffers函数来完成缓冲区刷新工作：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; DisplayDevice::swapBuffers(HWComposer&amp;amp; hwc) &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// We need to call eglSwapBuffers() if:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//  (1) we don&#39;t have a hardware composer, or&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//  (2) we did GLES composition this frame, and either&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//    (a) we have framebuffer target support (not present on legacy&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//        devices, where HWComposer::commit() handles things); or&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//    (b) this is a virtual display&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hwc.initCheck() != NO_ERROR ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            (hwc.hasGlesComposition(mHwcDisplayId) &amp;amp;&amp;amp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             (hwc.supportsFramebufferTarget() || mType &amp;gt;= DISPLAY_VIRTUAL))) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!success) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            EGLint error = eglGetError();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (error == EGL_CONTEXT_LOST ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    mType == DisplayDevice::DISPLAY_PRIMARY) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                LOG_ALWAYS_FATAL(&lt;span class=&quot;string&quot;&gt;&quot;eglSwapBuffers(%p, %p) failed with 0x%08x&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        mDisplay, mSurface, error);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;eglSwapBuffers(%p, %p) failed with 0x%08x&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        mDisplay, mSurface, error);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; result = mDisplaySurface-&amp;gt;advanceFrame();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (result != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;[%s] failed pushing new frame to HWC: %d&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mDisplayName.&lt;span class=&quot;built_in&quot;&gt;string&lt;/span&gt;(), result);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;但是注意调用swapBuffers输出图像是在显示设备不支持硬件composer的情况下。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;HWComposer设备&quot;&gt;&lt;a href=&quot;#HWComposer设备&quot; class=&quot;headerlink&quot; title=&quot;HWComposer设备&quot;&gt;&lt;/a&gt;HWComposer设备&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;通过上一篇文章得知，Android通过VSync机制来提高显示效果，那么VSync是如何产生的？通常这个信号是由显示驱动产生，这样才能达到最佳效果。但是Android为了能运行在不支持VSync机制的设备上，也提供了软件模拟产生VSync信号的手段。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在SurfaceFlinger中，是通过HWComposer类来表示硬件设备。我们继续产看init函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::init() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Initialize the H/W composer object.  There may or may not be an&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// actual hardware composer underneath.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mHwc = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; HWComposer(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            *&lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;HWComposer::EventHandler *&amp;gt;(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们继续查看HWComposer的构造函数，位于frameworks/native/services/surfaceflinger/displayhardware/HWComposer.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;96&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;97&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;98&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;99&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;100&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;101&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;102&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;103&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;104&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;105&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;106&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;107&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;108&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// ---------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;HWComposer::HWComposer(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;SurfaceFlinger&amp;gt;&amp;amp; flinger,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        EventHandler&amp;amp; handler)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    : mFlinger(flinger),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mFbDev(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;), mHwc(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;), mNumDisplays(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mCBContext(&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; cb_context),&lt;span class=&quot;comment&quot;&gt;//这里直接new了一个设备上下文对象&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mEventHandler(handler),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mDebugForceFakeVSync(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; needVSyncThread = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Note: some devices may insist that the FB HAL be opened before HWC.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//装载FrameBuffer的硬件模块 &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; fberr = loadFbHalModule();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//装载HWComposer的硬件模块,这个函数中会将mHwc置为true&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    loadHwcModule();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果有FB和HWC，并且也有pre-1.1 HWC，就要先关闭FB设备&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//但这个是暂时的，直到HWC准备好&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mFbDev &amp;amp;&amp;amp; mHwc &amp;amp;&amp;amp; hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// close FB HAL if we don&#39;t needed it.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;FIXME:&lt;/span&gt; this is temporary until we&#39;re not forced to open FB HAL&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// before HWC.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        framebuffer_close(mFbDev);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mFbDev = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果我们没有HWC硬件支持，或者之前的pre-1.1 HWC，如hwc 1.0,那么FrameBuffer就是必须的&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;amp;&amp;amp; !mFbDev) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果没有framebuffer，就退出gg&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;ERROR: failed to open framebuffer (%s), aborting&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                strerror(-fberr));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;built_in&quot;&gt;abort&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// these display IDs are always reserved&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; i&amp;lt;NUM_BUILTIN_DISPLAYS ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mAllocatedDisplayIDs.markBit(i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//硬件vsync信号&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mHwc) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGI(&lt;span class=&quot;string&quot;&gt;&quot;Using %s version %u.%u&quot;&lt;/span&gt;, HWC_HARDWARE_COMPOSER,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              (hwcApiVersion(mHwc) &amp;gt;&amp;gt; &lt;span class=&quot;number&quot;&gt;24&lt;/span&gt;) &amp;amp; &lt;span class=&quot;number&quot;&gt;0xff&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              (hwcApiVersion(mHwc) &amp;gt;&amp;gt; &lt;span class=&quot;number&quot;&gt;16&lt;/span&gt;) &amp;amp; &lt;span class=&quot;number&quot;&gt;0xff&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mHwc-&amp;gt;registerProcs) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//HWComposer设备上下文变量mCBContext赋值&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mCBContext-&amp;gt;hwc = &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//函数指针钩子函数hook_invalidate放入上下文&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mCBContext-&amp;gt;procs.invalidate = &amp;amp;hook_invalidate;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//vsync钩子函数放入上下文&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mCBContext-&amp;gt;procs.vsync = &amp;amp;hook_vsync;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//hotplug狗子函数放入上下文&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mCBContext-&amp;gt;procs.hotplug = &amp;amp;hook_hotplug;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mCBContext-&amp;gt;procs.hotplug = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;built_in&quot;&gt;memset&lt;/span&gt;(mCBContext-&amp;gt;procs.zero, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(mCBContext-&amp;gt;procs.zero));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//将钩子函数注册进硬件设备，硬件驱动回调这些钩子函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mHwc-&amp;gt;registerProcs(mHwc, &amp;amp;mCBContext-&amp;gt;procs);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// don&#39;t need a vsync thread if we have a hardware composer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果有硬件vsync信号， 则不需要软件vsync实现&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        needVSyncThread = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mFbDev) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//如果mFbDev为不为null，情况为：没有hwc或者hwc是1.0老的版本&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOG_ASSERT(!(mHwc &amp;amp;&amp;amp; hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;string&quot;&gt;&quot;should only have fbdev if no hwc or hwc is 1.0&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;function&quot;&gt;DisplayData&amp;amp; &lt;span class=&quot;title&quot;&gt;disp&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mDisplayData[HWC_DISPLAY_PRIMARY])&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        disp.connected = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        disp.format = mFbDev-&amp;gt;format;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        DisplayConfig config = DisplayConfig();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        config.width = mFbDev-&amp;gt;width;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        config.height = mFbDev-&amp;gt;height;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        config.xdpi = mFbDev-&amp;gt;xdpi;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        config.ydpi = mFbDev-&amp;gt;ydpi;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        config.refresh = &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt;(&lt;span class=&quot;number&quot;&gt;1e9&lt;/span&gt; / mFbDev-&amp;gt;fps);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        disp.configs.push_back(config);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        disp.currentConfig = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mHwc) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//如果mFbDev为null，情况为：fb打开失败，或者暂时关闭(上面逻辑分析了)。打开了hwc&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// here we&#39;re guaranteed to have at least HWC 1.1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//这里我们至少有HWC 1.1，上面分析过了。NUM_BUILTIN_DISPLAYS 为2&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i =&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; i&amp;lt;NUM_BUILTIN_DISPLAYS ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//获取显示设备相关属性&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            queryDisplayProperties(i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果没有硬件vsync，则需要用使用软件vsync模拟&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (needVSyncThread) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// we don&#39;t have VSYNC support, we need to fake it&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mVSyncThread = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; VSyncThread(*&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;构造函数主要做了以下几件事情：&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）加载FrameBuffer硬件驱动：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;调用loadFbHalModule函数实现，我们继续查看：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// Load and prepare the FB HAL, which uses the gralloc module.  Sets mFbDev.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; HWComposer::loadFbHalModule()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;hw_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* module;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//hal层封装的hal函数，参数GRALLOC_HARDWARE_MODULE_ID，加载gralloc模块&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &amp;amp;module);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;%s module not found&quot;&lt;/span&gt;, GRALLOC_HARDWARE_MODULE_ID);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//打开fb设备&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; framebuffer_open(module, &amp;amp;mFbDev);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;hw_get_module&lt;/strong&gt;函数是HAL层框架中封装的加载gralloc的函数，这个我们之前讲过，可以查看&lt;a href=&quot;http://windrunnerlihuan.com/2017/03/12/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B8%80-Android%E5%9B%BE%E5%BD%A2%E6%98%BE%E7%A4%BA%E4%B9%8BHAL%E5%B1%82Gralloc%E6%A8%A1%E5%9D%97%E5%AE%9E%E7%8E%B0/&quot;&gt;Android SurfaceFlinger 学习之路(一)—-Android图形显示之HAL层Gralloc模块实现&lt;/a&gt;中的&lt;strong&gt;Gralloc模块的加载过程&lt;/strong&gt;部分。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;framebuffer_open&lt;/strong&gt;函数同上，是用来打开fb设备，同样查看&lt;code&gt;fb设备的打开过程&lt;/code&gt;模块。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）装载HWComposer的硬件模块：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;调用loadHwcModule函数来加载HWC模块，我们继续查看：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// Load and prepare the hardware composer module.  Sets mHwc.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; HWComposer::loadHwcModule()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;hw_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* module;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//同样是HAL层封装的函数，参数是HWC_HARDWARE_MODULE_ID，加载hwc模块&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hw_get_module(HWC_HARDWARE_MODULE_ID, &amp;amp;module) != &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;%s module not found&quot;&lt;/span&gt;, HWC_HARDWARE_MODULE_ID);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//打开hwc设备&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; err = hwc_open_1(module, &amp;amp;mHwc);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;%s device failed to initialize (%s)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              HWC_HARDWARE_COMPOSER, strerror(-err));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0) ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hwcHeaderVersion(mHwc) &amp;lt; MIN_HWC_HEADER_VERSION ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            hwcHeaderVersion(mHwc) &amp;gt; HWC_HEADER_VERSION) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;%s device version %#x unsupported, will not be used&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              HWC_HARDWARE_COMPOSER, mHwc-&amp;gt;common.version);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        hwc_close_1(mHwc);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mHwc = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;同样是借助&lt;strong&gt;hw_get_module&lt;/strong&gt;这个HAL函数，不过参数是HWC_HARDWARE_MODULE_ID，加载HWC模块；然后&lt;strong&gt;hwc_open_1&lt;/strong&gt;函数打开hwc设备。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）FB和HWC相关逻辑判断(1)：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果有FB和HWC，并且也有pre-1.1 HWC，就要先关闭FB设备。这个是暂时的，直到HWC准备好；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果我们没有HWC硬件支持，或者之前的pre-1.1 HWC,，如HWC 1.0，那么FrameBuffer就是必须的。如果脸FB都没有，那就GG。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）硬件设备打开成功：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果硬件设备打开成功，则将钩子函数&lt;strong&gt;hook_invalidate、hook_vsync和hook_hotplug&lt;/strong&gt;注册进硬件设备，作为回调函数。这三个都是硬件产生事件信号，通知上层SurfaceFlinger的回调函数，用于处理这个信号。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;因为我们本节是Vsync信号相关，所以我们只看看hook_vsync钩子函数。这里指定了vsync的回调函数是hook_vsync，如果硬件中产生了VSync信号，将通过这个函数来通知上层，看看它的代码：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; HWComposer::hook_vsync(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; hwc_procs* procs, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; disp,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int64_t&lt;/span&gt; timestamp) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    cb_context* ctx = &lt;span class=&quot;keyword&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;cb_context*&amp;gt;(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;hwc_procs_t&lt;/span&gt;*&amp;gt;(procs));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ctx-&amp;gt;hwc-&amp;gt;vsync(disp, timestamp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;hook_vsync钩子函数会调用vsync函数，我们继续看：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; HWComposer::vsync(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; disp, &lt;span class=&quot;keyword&quot;&gt;int64_t&lt;/span&gt; timestamp) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;(disp) &amp;lt; HWC_NUM_PHYSICAL_DISPLAY_TYPES) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Mutex::Autolock _l(mLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// There have been reports of HWCs that signal several vsync events&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// with the same timestamp when turning the display off and on. This&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// is a bug in the HWC implementation, but filter the extra events&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// out here so they don&#39;t cause havoc downstream.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (timestamp == mLastHwVSync[disp]) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ALOGW(&lt;span class=&quot;string&quot;&gt;&quot;Ignoring duplicate VSYNC event from HWC (t=%&quot;&lt;/span&gt; PRId64 &lt;span class=&quot;string&quot;&gt;&quot;)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        timestamp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mLastHwVSync[disp] = timestamp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; tag[&lt;span class=&quot;number&quot;&gt;16&lt;/span&gt;];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;built_in&quot;&gt;snprintf&lt;/span&gt;(tag, &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(tag), &lt;span class=&quot;string&quot;&gt;&quot;HW_VSYNC_%1u&quot;&lt;/span&gt;, disp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ATRACE_INT(tag, ++mVSyncCounts[disp] &amp;amp; &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//这里调用EventHandler类型变量mEventHandler就是SurfaceFlinger，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//所以调用了SurfaceFlinger的onVSyncReceived函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mEventHandler.onVSyncReceived(disp, timestamp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;mEventHandler对象类型为EventHandler，我们在SurfaceFlinger的init函数创建HWComposer类实例时候讲SurfaceFlinger强转为EventHandler作为构造函数的参数传入其中。再者SurfaceFlinger继承HWComposer::EventHandler，所以这里没毛病，老铁~所以最终会调用SurfaceFlinger的onVSyncReceived函数。这就是硬件vsync信号的产生，关于vsync信号流程工作我们下面马上会讲到。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;5）FB和HWC相关逻辑判断(2)：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果mFbDev为不为null，情况为：没有hwc或者hwc是1.0老的版本。此时就要设置一些FB的属性了，从主屏幕获取；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果mFbDev为null，情况为：fb打开失败，或者暂时关闭(上面逻辑分析了)。仅仅打开了hwc，这里我们至少有HWC 1.1，上面分析过了。此时我们要获取显示设备相关属性，进入else if逻辑判断，里面的NUM_BUILTIN_DISPLAYS 为2，则只有主屏幕和扩展屏幕需要查询显示设备属性，调用queryDisplayProperties函数，我们可以产看这个函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; HWComposer::queryDisplayProperties(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; disp) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// use zero as default value for unspecified attributes&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; values[NUM_DISPLAY_ATTRIBUTES - &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;built_in&quot;&gt;memset&lt;/span&gt;(values, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(values));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; MAX_NUM_CONFIGS = &lt;span class=&quot;number&quot;&gt;128&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; configs[MAX_NUM_CONFIGS] = &amp;#123;&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; numConfigs = MAX_NUM_CONFIGS;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//hwc设备获取显屏配置信息，都是HAL层封装的函数，并保存在这些指针指向内容中&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = mHwc-&amp;gt;getDisplayConfigs(mHwc, disp, configs, &amp;amp;numConfigs);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果一个不可插入的显屏没有连接，则将connected赋值为false&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// this can happen if an unpluggable display is not connected&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mDisplayData[disp].connected = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDisplayData[disp].currentConfig = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//获取显示相关属性&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; c = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; c &amp;lt; numConfigs; ++c) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        err = mHwc-&amp;gt;getDisplayAttributes(mHwc, disp, configs[c],&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                DISPLAY_ATTRIBUTES, values);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// we can&#39;t get this display&#39;s info. turn it off.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mDisplayData[disp].connected = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//获取成功后，创建一个config对象，用于保存这些属性&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        DisplayConfig config = DisplayConfig();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; NUM_DISPLAY_ATTRIBUTES - &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt; (DISPLAY_ATTRIBUTES[i]) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HWC_DISPLAY_VSYNC_PERIOD:&lt;span class=&quot;comment&quot;&gt;//屏幕刷新率&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    config.refresh = &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt;(values[i]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HWC_DISPLAY_WIDTH:&lt;span class=&quot;comment&quot;&gt;//屏幕宽&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    config.width = values[i];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HWC_DISPLAY_HEIGHT:&lt;span class=&quot;comment&quot;&gt;//屏幕高&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    config.height = values[i];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HWC_DISPLAY_DPI_X:&lt;span class=&quot;comment&quot;&gt;//DPI像素X&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    config.xdpi = values[i] / &lt;span class=&quot;number&quot;&gt;1000.0f&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HWC_DISPLAY_DPI_Y:&lt;span class=&quot;comment&quot;&gt;//DPI像素Y&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    config.ydpi = values[i] / &lt;span class=&quot;number&quot;&gt;1000.0f&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;default&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    ALOG_ASSERT(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&quot;unknown display attribute[%zu] %#x&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            i, DISPLAY_ATTRIBUTES[i]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果没有获取到DPI则给个默认的，跟进去是213或者320&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (config.xdpi == &lt;span class=&quot;number&quot;&gt;0.0f&lt;/span&gt; || config.ydpi == &lt;span class=&quot;number&quot;&gt;0.0f&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;float&lt;/span&gt; dpi = getDefaultDensity(config.width, config.height);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            config.xdpi = dpi;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            config.ydpi = dpi;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//将每个设备的显示信息存起来&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mDisplayData[disp].configs.push_back(config);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;FIXME:&lt;/span&gt; what should we set the format to?&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//像素编码都为ARGB_8888&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDisplayData[disp].format = HAL_PIXEL_FORMAT_RGBA_8888;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//这里讲connected复制为true&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDisplayData[disp].connected = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;queryDisplayProperties查询每个显示设备的属性，主要有以下几步：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;hwc设备获取显屏配置信息，都是HAL层封装的函数，并保存在这些指针指向内容中;&lt;/li&gt;
&lt;li&gt;获取显示先关属性，并保存起来。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这一部分注释写的比较清晰，可以查看注释。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;6）软件VSync信号产生：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果硬件设备打开失败，则需要软件vsync信号，因此&lt;strong&gt;needVSyncThread&lt;/strong&gt;为true，会进入最后一个if条件判断逻辑，则会创建一个VSyncThread类实例，用来模拟软件vsync信号。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以我们看看VSyncThread这个类，它集成与Thread，又是一个线程，定义位于HWComposer.h中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// this class is only used to fake the VSync event on systems that don&#39;t&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// have it.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; VSyncThread : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; Thread &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    HWComposer&amp;amp; mHwc;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;mutable&lt;/span&gt; Mutex mLock;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Condition mCondition;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; mEnabled;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;mutable&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; mNextFakeVSync;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; mRefreshPeriod;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;onFirstRef&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;threadLoop&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    VSyncThread(HWComposer&amp;amp; hwc);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;setEnabled&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; enabled)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;构造函数位于HWComposer.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;HWComposer::VSyncThread::VSyncThread(HWComposer&amp;amp; hwc)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    : mHwc(hwc), mEnabled(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;span class=&quot;comment&quot;&gt;//false&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mNextFakeVSync(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;span class=&quot;comment&quot;&gt;//0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mRefreshPeriod(hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY))&lt;span class=&quot;comment&quot;&gt;//获取主屏幕刷新率&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;构造函数中初始化了mEnable变量为false，mNextFakeVSync为0。还有获取了主屏幕的刷新率，并保存在mRefreshPeriod。屏幕刷新率我们在上一篇&lt;a href=&quot;http://windrunnerlihuan.com/2017/05/21/VSync%E4%BF%A1%E5%8F%B7/&quot;&gt;VSync信号&lt;/a&gt;已经科普过了。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们看看屏幕刷新率的获取，hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY)函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; HWComposer::getRefreshPeriod(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; disp) &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; currentConfig = mDisplayData[disp].currentConfig;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mDisplayData[disp].configs[currentConfig].refresh;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里获取的屏幕刷新率refresh就是我们之前queryDisplayProperties函数里获取的。其实queryDisplayProperties不止在HWComposer构造函数里调用，还会在钩子函数hook_hotplug里调用，我们查看hotplug函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; HWComposer::hotplug(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; disp, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; connected) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (disp == HWC_DISPLAY_PRIMARY || disp &amp;gt;= VIRTUAL_DISPLAY_ID_BASE) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;hotplug event received for invalid display: disp=%d connected=%d&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                disp, connected);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    queryDisplayProperties(disp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEventHandler.onHotplugReceived(disp, &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt;(connected));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果是主屏幕或者虚拟设备则不会查询设备属性。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我猜测是插入扩展屏幕后，会重新再查询一下屏幕信息，从硬件发出的信号。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;好了我们继续回到上面，因为VSyncThread对象付给了一个强指针，所以会调用onFirstRef函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; HWComposer::VSyncThread::onFirstRef() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    run(&lt;span class=&quot;string&quot;&gt;&quot;VSyncThread&quot;&lt;/span&gt;, PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这样这个软件vsync产生线程就运行起来了，因此我们需要查看threadLoop函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; HWComposer::VSyncThread::threadLoop() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123; &lt;span class=&quot;comment&quot;&gt;// scope for lock&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Mutex::Autolock _l(mLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (!mEnabled) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//这个是false，在构造函数里赋值&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//因此会阻塞在这里&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mCondition.wait(mLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; period = mRefreshPeriod;&lt;span class=&quot;comment&quot;&gt;//屏幕刷新率&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; now = systemTime(CLOCK_MONOTONIC);&lt;span class=&quot;comment&quot;&gt;//now&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; next_vsync = mNextFakeVSync;&lt;span class=&quot;comment&quot;&gt;//下一次vsync时间，初始值为0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; sleep = next_vsync - now;&lt;span class=&quot;comment&quot;&gt;//距离下次vsync信号中间的睡眠时间&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (sleep &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//如果sleep小于0，比如第一次进来mNextFakeVSync为0；或者错过n次vsync信号&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// we missed, find where the next vsync should be&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果错过了，则重新计算下一次vsync的偏移时间&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sleep = (period - ((now - next_vsync) % period));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        next_vsync = now + sleep;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//偏移时间加上刷新率周期时间&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mNextFakeVSync = next_vsync + period;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; timespec spec;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    spec.tv_sec  = next_vsync / &lt;span class=&quot;number&quot;&gt;1000000000&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    spec.tv_nsec = next_vsync % &lt;span class=&quot;number&quot;&gt;1000000000&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;do&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//然后睡眠等待下次vsync信号的时间&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &amp;amp;spec, &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (err&amp;lt;&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; &amp;amp;&amp;amp; errno == EINTR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//睡眠ok后，则去驱动SurfaceFlinger函数触发&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mHwc.mEventHandler.onVSyncReceived(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, next_vsync);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面的代码，我们需要注意两个地方： &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;mEnabled默认为false，mCondition在这里阻塞，直到有人调用了signal()，同时mEnabled为true；&lt;/li&gt;
&lt;li&gt;如果阻塞解开，则会定期休眠，然后去驱动SF，这就相当于产生了持续的Vsync信号。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个函数会间隔模拟产生VSync的信号的原理是在固定时间发送消息给HWCompoer的消息对象mEventHandler，这个其实就到SurfaceFlinger的onVSyncReceived函数了。用软件模拟VSync信号在系统比较忙的时候可能会丢失一些信号，所以才有中间的sleep小于0的情况。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;到目前为止，HWC中新建了一个线程VSyncThread，阻塞中，下面我们看下打开Vsync开关的闸刀是如何建立的，以及何处去开闸刀。&lt;/p&gt;
&lt;h1 id=&quot;VSync-信号闸刀控制&quot;&gt;&lt;a href=&quot;#VSync-信号闸刀控制&quot; class=&quot;headerlink&quot; title=&quot;VSync 信号闸刀控制&quot;&gt;&lt;/a&gt;VSync 信号闸刀控制&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面我分析了Vsync软件和硬件信号的产生过程，但是HWC中新建的线程VSyncThread是处于阻塞当中，因此我们需要一个闸刀去控制这个开关。&lt;/p&gt;
&lt;h2 id=&quot;Vsync信号开关&quot;&gt;&lt;a href=&quot;#Vsync信号开关&quot; class=&quot;headerlink&quot; title=&quot;Vsync信号开关&quot;&gt;&lt;/a&gt;Vsync信号开关&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个闸刀还是在SurfaceFlinger的init函数中建立的，我们查看这个位置：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::init() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEventControlThread = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; EventControlThread(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEventControlThread-&amp;gt;run(&lt;span class=&quot;string&quot;&gt;&quot;EventControl&quot;&lt;/span&gt;, PRIORITY_URGENT_DISPLAY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这是一个Thread线程类，因此都会实现threadLoop函数。不过我们先看看它的构造函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;EventControlThread::EventControlThread(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;SurfaceFlinger&amp;gt;&amp;amp; flinger):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mFlinger(flinger),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mVsyncEnabled(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;比较简单，将SurfaceFlinger对象传了进来，并且将mVsyncEnabled标志初始为false。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后我们看看他的threadLoop线程函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; EventControlThread::threadLoop() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; vsyncEnabled = mVsyncEnabled;&lt;span class=&quot;comment&quot;&gt;//初始为false&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//先调用一遍SurfaceFlinger的eventControl函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFlinger-&amp;gt;eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mVsyncEnabled);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//这里是个死循环&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = mCond.wait(mMutex);&lt;span class=&quot;comment&quot;&gt;//会阻塞在这里&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;error waiting for new events: %s (%d)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                strerror(-err), err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//vsyncEnabled 开始和mVsyncEnabled都为false，如果有其他地方改变了mVsyncEnabled,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//会去调用SF的eventControl函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (vsyncEnabled != mVsyncEnabled) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mFlinger-&amp;gt;eventControl(HWC_DISPLAY_PRIMARY,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    SurfaceFlinger::EVENT_VSYNC, mVsyncEnabled);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            vsyncEnabled = mVsyncEnabled;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;threadLoop函数主要逻辑分两步：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1.进来时候在mCond处阻塞，可以看到外面是个死循环，所以如果有其他地方对这个mCond调用了signal，执行完下面的代码又会阻塞 ；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2.解除阻塞后，如果vsyncEnabled != mVsyncEnabled，也就是开关状态不同，由开到关和由关到开，都回去调用mFlinger-&amp;gt;eventControl，调用完成后把这次的开关状态保存，vsyncEnabled = mVsyncEnabled;，与下次做比较。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从上面我们能明显认识到EventControlThread线程，其实就起到了个闸刀的作用，等待着别人去开、关。 &lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以这个开关操作就在SurfaceFlinger的eventControl函数，我们看看它怎么实现：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::eventControl(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; disp, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; event, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; enabled) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    getHwComposer().eventControl(disp, event, enabled);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;它又会调用HWComposer的eventControl函数，我们继续查看：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; HWComposer::eventControl(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; disp, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; event, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; enabled) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果是没有申请注册的设备，GG&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;(disp)&amp;gt;&lt;span class=&quot;number&quot;&gt;31&lt;/span&gt; || !mAllocatedDisplayIDs.hasBit(disp)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGD(&lt;span class=&quot;string&quot;&gt;&quot;eventControl ignoring event %d on unallocated disp %d (en=%d)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              event, disp, enabled);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//不是EVENT_VSYNC事件，GG&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (event != EVENT_VSYNC) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGW(&lt;span class=&quot;string&quot;&gt;&quot;eventControl got unexpected event %d (disp=%d en=%d)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              event, disp, enabled);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果是硬件Vsync闸刀，并且不是调试软件vsync&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mHwc &amp;amp;&amp;amp; !mDebugForceFakeVSync) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;NOTE:&lt;/span&gt; we use our own internal lock here because we have to call&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// into the HWC with the lock held, and we want to make sure&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// that even if HWC blocks (which it shouldn&#39;t), it won&#39;t&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// affect other threads.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Mutex::Autolock _l(mEventControlLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; eventBit = &lt;span class=&quot;number&quot;&gt;1U&lt;/span&gt;L &amp;lt;&amp;lt; event;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; newValue = enabled ? eventBit : &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; oldValue = mDisplayData[disp].events &amp;amp; eventBit;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (newValue != oldValue) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//硬件vsync闸刀控制开关&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            err = mHwc-&amp;gt;eventControl(mHwc, disp, event, enabled);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!err) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt;&amp;amp; events(mDisplayData[disp].events);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                events = (events &amp;amp; ~eventBit) | newValue;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; tag[&lt;span class=&quot;number&quot;&gt;16&lt;/span&gt;];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;built_in&quot;&gt;snprintf&lt;/span&gt;(tag, &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(tag), &lt;span class=&quot;string&quot;&gt;&quot;HW_VSYNC_ON_%1u&quot;&lt;/span&gt;, disp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ATRACE_INT(tag, enabled);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// error here should not happen -- not sure what we should&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// do if it does.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE_IF(err, &lt;span class=&quot;string&quot;&gt;&quot;eventControl(%d, %d) failed %s&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                event, enabled, strerror(-err));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果没有硬件Vsync支持，则调用软件vsync信号闸刀&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == NO_ERROR &amp;amp;&amp;amp; mVSyncThread != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mVSyncThread-&amp;gt;setEnabled(enabled);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里可以看到还是分软件闸刀和硬件闸刀：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;硬件闸刀控制就到了HAL层函数了，调用了mHwc-&amp;gt;eventControl(mHwc, disp, event, enabled)这个逻辑；&lt;/li&gt;
&lt;li&gt;如果没有硬件Vsync支持，则会调用软件闸刀控制手段，VsyncThread的setEnable函数。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;硬件就不用了看，反正也看不到代码。。。我们看看软件Vsync闸刀控制，即VsyncThread的setEnable函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; HWComposer::VSyncThread::setEnabled(&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; enabled) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::Autolock _l(mLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mEnabled != enabled) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mEnabled = enabled;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mCondition.signal();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;将软件模拟线程VSyncThread的mCondition释放，这时候VSyncThread就会定期产生“信号”，去驱动SF了。&lt;/p&gt;
&lt;h2 id=&quot;EventControlThread开关&quot;&gt;&lt;a href=&quot;#EventControlThread开关&quot; class=&quot;headerlink&quot; title=&quot;EventControlThread开关&quot;&gt;&lt;/a&gt;EventControlThread开关&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;但是我们上边漏了东西，就是EventControlThread本身的闸刀，它自己还在mCond.wait(mMutex)这里阻塞呢。那么EventControlThread这个闸刀到底在哪儿打开呢？&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以我们还得的查看SurfaceFlinger的init函数，再这里它有一处逻辑：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::init() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// set initial conditions (e.g. unblank default device)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    initializeDisplays();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们查看initializeDisplays函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::initializeDisplays() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; MessageScreenInitialized : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; MessageBase &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        SurfaceFlinger* flinger;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        MessageScreenInitialized(SurfaceFlinger* flinger) : flinger(flinger) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            flinger-&amp;gt;onInitializeDisplays();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;MessageBase&amp;gt; msg = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; MessageScreenInitialized(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    postMessageAsync(msg);  &lt;span class=&quot;comment&quot;&gt;// we may be called from main thread, use async message&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里放了一个消息给SF的MessageQueue，然后消息回调onInitializeDisplays函数，我们继续查看：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::onInitializeDisplays() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// reset screen orientation and use primary layer stack&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//重置屏幕方向，并使用主屏幕图层&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Vector&amp;lt;ComposerState&amp;gt; state;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Vector&amp;lt;DisplayState&amp;gt; displays;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    DisplayState d;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    d.what = DisplayState::eDisplayProjectionChanged |&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             DisplayState::eLayerStackChanged;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    d.token = mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    d.layerStack = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    d.orientation = DisplayState::eOrientationDefault;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    d.frame.makeInvalid();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    d.viewport.makeInvalid();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    d.width = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    d.height = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    displays.add(d);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//重设屏幕Transaction状态&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    setTransactionState(state, displays, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//我们要找到闸刀开关在这个里面&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//主显示器刷新率&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; period =&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mAnimFrameTracker.setDisplayRefreshPeriod(period);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;其它都不重要，重要在setPowerModeInternal函数，我们继续查看：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::setPowerModeInternal(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;DisplayDevice&amp;gt;&amp;amp; hw,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; mode) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//HWC_POWER_MODE_NORMAL&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGD(&lt;span class=&quot;string&quot;&gt;&quot;Set power mode=%d, type=%d flinger=%p&quot;&lt;/span&gt;, mode, hw-&amp;gt;getDisplayType(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; type = hw-&amp;gt;getDisplayType();&lt;span class=&quot;comment&quot;&gt;//DISPLAY_PRIMARY&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; currentMode = hw-&amp;gt;getPowerMode();&lt;span class=&quot;comment&quot;&gt;//HWC_POWER_MODE_OFF&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mode == currentMode) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//skip&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGD(&lt;span class=&quot;string&quot;&gt;&quot;Screen type=%d is already mode=%d&quot;&lt;/span&gt;, hw-&amp;gt;getDisplayType(), mode);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    hw-&amp;gt;setPowerMode(mode);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (type &amp;gt;= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGW(&lt;span class=&quot;string&quot;&gt;&quot;Trying to set power mode for virtual display&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (currentMode == HWC_POWER_MODE_OFF) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//会走到这里&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        getHwComposer().setPowerMode(type, mode);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (type == DisplayDevice::DISPLAY_PRIMARY) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;FIXME:&lt;/span&gt; eventthread only knows about the main display right now&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//EventThread是后面讲到VSync工作流程的部分，后面讲，这里影响不大&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mEventThread-&amp;gt;onScreenAcquired();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//这里才是重点，是打开闸刀的地方&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            resyncToHardwareVsync(&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mVisibleRegionsDirty = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        repaintEverything();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mode == HWC_POWER_MODE_OFF) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//不会到这里&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (type == DisplayDevice::DISPLAY_PRIMARY) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disableHardwareVsync(&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;); &lt;span class=&quot;comment&quot;&gt;// also cancels any in-progress resync&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;FIXME:&lt;/span&gt; eventthread only knows about the main display right now&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mEventThread-&amp;gt;onScreenReleased();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        getHwComposer().setPowerMode(type, mode);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mVisibleRegionsDirty = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// from this point on, SF will stop drawing on this display&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;span class=&quot;comment&quot;&gt;//也不会到这儿&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        getHwComposer().setPowerMode(type, mode);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面逻辑也不难，只要我们记住以前赋值的变量时多少就行了。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们获取主显屏的信息，因为是灭的HWC_POWER_MODE_OFF模式，所以进入这个if判断里面，然后调用resyncToHardwareVsync函数。我们继续查看它：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::resyncToHardwareVsync(&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; makeAvailable) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//true&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::Autolock _l(mHWVsyncLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//true&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (makeAvailable) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mHWVsyncAvailable = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mHWVsyncAvailable) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;resyncToHardwareVsync called when HW vsync unavailable&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//主屏幕硬件刷新率&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; period =&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//设置硬件刷新率&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mPrimaryDispSync.reset();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mPrimaryDispSync.setPeriod(period);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mPrimaryHWVsyncEnabled) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//false,进入&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mPrimaryDispSync.beginResync();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//打开闸刀&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mEventControlThread-&amp;gt;setVsyncEnabled(&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mPrimaryHWVsyncEnabled = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;先将mHWVsyncAvailable 标志位置为true，然后设置硬件刷新周期，最后打开mEventControlThread闸刀，我们可以查看它的setVsyncEnabled函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; EventControlThread::setVsyncEnabled(&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; enabled) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mVsyncEnabled = enabled;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCond.signal();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;可以看到，在这里释放了前面的mCond，让EventControlThread去调用mFlinger-&amp;gt;eventControl()函数，从而去HWC中打开Vsync开关。&lt;/p&gt;
&lt;h1 id=&quot;VSync信号构成&quot;&gt;&lt;a href=&quot;#VSync信号构成&quot; class=&quot;headerlink&quot; title=&quot;VSync信号构成&quot;&gt;&lt;/a&gt;VSync信号构成&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;本来我们应该继续顺着代码去跟踪vsync信号的分发过程，但是在这之前我们有必要了解一下vsync信号的构成，以便我们后续分析没有盲点。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们知道Android是用Vsync来驱动系统的画面更新包括APPview draw ,surfaceflinger 画面的合成,display把surfaceflinger合成的画面呈现在LCD上。要分析Vsync信号的组成，可以了解一下&lt;strong&gt;systrace工具&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id=&quot;Systrace简介&quot;&gt;&lt;a href=&quot;#Systrace简介&quot; class=&quot;headerlink&quot; title=&quot;Systrace简介&quot;&gt;&lt;/a&gt;Systrace简介&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Systrace是Android4.1中新增的性能数据采样和分析工具。它可帮助开发者收集Android关键子系统（如surfaceflinger、WindowManagerService等Framework部分关键模块、服务，View系统等）的运行信息，从而帮助开发者更直观的分析系统瓶颈，改进性能。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;systrace的使用可以查看官网，或者问&lt;code&gt;娘&lt;/code&gt;问&lt;code&gt;哥&lt;/code&gt;。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;官网使用教程如下：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;a href=&quot;https://developer.android.com/studio/profile/systrace-walkthru.html&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;https://developer.android.com/studio/profile/systrace-walkthru.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;命令行使用方式：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;a href=&quot;https://developer.android.com/studio/profile/systrace-commandline.html&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;https://developer.android.com/studio/profile/systrace-commandline.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;生成html分析：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;a href=&quot;https://developer.android.com/studio/profile/systrace.html&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;https://developer.android.com/studio/profile/systrace.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;分析systrace生成文件，要在eng版本rom，其他的要么无法生成，要么没有权限。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;下面我抄一个例子分析。&lt;/p&gt;
&lt;h2 id=&quot;VSync的构成&quot;&gt;&lt;a href=&quot;#VSync的构成&quot; class=&quot;headerlink&quot; title=&quot;VSync的构成&quot;&gt;&lt;/a&gt;VSync的构成&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;就挑一个&lt;code&gt;相册&lt;/code&gt;这个应用，是系统自带的system app，包名是com.android.gallery3d。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%94%29----VSync%20%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/systrace1.png&quot; alt=&quot;Systrace1&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在systrace中,我们经常可以看到如上图的信息。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;红色框1是与Vsync相关event信息.这些Vsync event构成了android系统画面更新基础；&lt;/li&gt;
&lt;li&gt;红色框2和红色框3是Vsync-app的信息.我们可以看到红色框2比红色框3稀疏.我们将会在本文说明其原因；&lt;/li&gt;
&lt;li&gt;红色框4和红色框5是Vsync-sf的信息.我们可以看到红色框4比红色框5稀疏.我们将会在本文说明其原因。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从上图可以看出来，VSync信号由HW_VSYNC_ON_0,HW_VSYNC_0, Vsync-app和Vsync-sf四部分构成：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;HW_VSYNC_ON_0&lt;/strong&gt;：代表PrimaryDisplay的VSync被enable或disable。0这个数字代表的是display的编号, 0是PrimaryDisplay,如果是Externalmonitor,就会是HW_VSYNC_ON_1。当SF要求HWComposer将Display的VSync打开或关掉时,这个event就会记录下来；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HW_VSYNC_0&lt;/strong&gt;：代表PrimaryDisplay的VSync发生时间点, 0同样代表display编号。其用来调节Vsync-app和Vsync-sfevent的输出；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vsync-app&lt;/strong&gt;：App,SystemUI和systemserver 等viewdraw的触发器；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vsync-sf&lt;/strong&gt;：Surfaceflinger合成画面的触发器。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;通常为了避免Tearing的现象，画面更新(Flip)的动作通常会在VSync开始的时候才做，因为在VSync开始到它结束前，Display不会把framebuffer资料显示在display上，所以在这段时间做Flip可以避免使用者同时看到前后两个部份画面的现象。&lt;strong&gt;目前user看到画面呈现的过程是这样的，app更新它的画面后，它需要透过BufferQueue通知SF，SF再将更新过的app画面与其它的App或SystemUI组合后，再显示在User面前&lt;/strong&gt;。在这个过程里,有3个component牵涉进来，分别是App、SF、与Display。以目前Android的设计，这三个Component都是在VSync发生的时候才开始做事。我们将它们想成一个有3个stage的pipeline，这个pipeline的clock就LCD的TE信号(60HZ)也即HW_VSYNC_0。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们来看看android draw的pipeline，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%94%29----VSync%20%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/pipeline.png&quot; alt=&quot;pipeline&quot;&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;T = 0时, App正在画N, SF与Display都没内容可用&lt;/li&gt;
&lt;li&gt;T = 1时, App正在画N+1, SF组合N, Display没Buffer可显示&lt;/li&gt;
&lt;li&gt;T = 2时, App正在画N+2, SF组合N+1, Display显示N&lt;/li&gt;
&lt;li&gt;T = 3时, App正在画N, SF组合N+2, Display显示N+1&lt;/li&gt;
&lt;li&gt;……&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果按照这个步骤，当user改变一个画面时，要等到2个VSync后，画面才会显示在user面前，latency大概是33ms (2个frame的时间)。但是对大部份的操作来讲，可能app加SF画的时间一个frame(16.6ms)就可以完成。因此，Android就从HW_VSYNC_0中产生出两个VSync信号，VSYNC-app是给App用的，VSYNC-sf是给SF用的， Display则是使用HW_VSYNC_0。VSYNC-app与VSYNC-sf可以分别给定一个phase，简单的说：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;VSYNC-app = HW_VSYNC_0 + phase_app&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;VSYNC-sf =HW_VSYNC_0 + phase_sf&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从而使App draw和surfaceflinger的合成，错开时间运行。这样就有可能整个系统draw的pipeline更加有效率，从而提高用户体验。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%94%29----VSync%20%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/phase.jpg&quot; alt=&quot;phase&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;也就是说，如果phase_app与phase_sf设定的好的话，可能大部份user使用的状况， App+SF可以在一个frame里完成，然后在下一个HW_VSYNC_0来的时候,显示在display上。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;理论上透过VSYNC-sf与VSYNC-app的确是可以有机会在一个frame里把App+SF做完，但是实际上不是一定可以在一个frame里完成。因为有可能因为CPU调度，GPUperformance不够，以致App或SF没办法及时做完。&lt;/strong&gt;但是即便如此，把app，surfaceflinger和displayVsync分开也比用一个Vsync来trigger appdraw，surfaceflinger合成，display在LCD上draw的性能要好很多(FPS更高)。因为如果放在同一时间，CPU调度压力更大，可能会卡顿、延迟。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;那么是否我们收到LCD的Vsync event就会触发Vsync-app和Vsync-SF呢？如果是这样我们就不会看到本文开头的Vsync-app和Vsync-SF的节奏不一致的情况(红色框2比红色框3稀疏)。事实上，在大多数情况下，APP的画面并不需要一直更新。比如我们看一篇文章，大部份时间，画面是维持一样的，如果我们在每个LCD的VSYNC来的时候都触发SF或APP，就会浪费时间和Power。可是在画面持续更新的情况下，我们又需要触发SF和App的Vsync event。例如玩game或播影片时。就是说我们需要根据是否有内容的更新来选择Vsync event出现的机制。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;Vsync event 的触发需要按需出现。&lt;/strong&gt;所以在Android里，HW_VSYNC_0，Vsync-sf和Vsync-app都会按需出现。HW_VSYNC_0是根据是否需要调节sf和app的Vsync event而出现，而SF和App则会call requestNextVsync()来告诉系统我要在下一个VSYNC需要被trigger。也是虽然系统每秒有60个HW VSYNC，但不代表APP和SF在每个VSYNC都要更新画面。&lt;strong&gt;因此，在Android里，是根据SoftwareVSYNC(Vsync-sf，Vsync-app)来更新画面&lt;/strong&gt;。Software VSYNC是根据HWVSYNC过去发生的时间，推测未来会发生的时间。因此，当APP或SF利用requestNextVsync时，Software VSYNC才会触发VSYNC-sf或VSYNC-app。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;下面我们就继续跟着代码，分析VSync信号工作流程。&lt;/p&gt;
&lt;h1 id=&quot;VSync工作流程&quot;&gt;&lt;a href=&quot;#VSync工作流程&quot; class=&quot;headerlink&quot; title=&quot;VSync工作流程&quot;&gt;&lt;/a&gt;VSync工作流程&lt;/h1&gt;&lt;h2 id=&quot;整体概述&quot;&gt;&lt;a href=&quot;#整体概述&quot; class=&quot;headerlink&quot; title=&quot;整体概述&quot;&gt;&lt;/a&gt;整体概述&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们知道Vsync是android display系统的重要基石,其驱动android display系统不断的更新App侧的绘画,并把相关内容及时的更新到LCD上.其包含的主要代码如下:&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;frameworks\native\services\surfaceflinger\DispSync.cpp&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp$DispSyncSource&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;frameworks\native\services\surfaceflinger\EventThread.cpp&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;frameworks\native\services\surfaceflinger\MessageQueue.cpp&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;frameworks\native\libs\gui\BitTube.cpp&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;frameworks\native\libs\gui\BufferQueueProducer.cpp&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DispSync.cpp：这个class包含了DispSyncThread，是SW-SYNC的心脏，所有的SW-SYNCevent均由其产生。在Android系统中,只有一个DispSync；&lt;/li&gt;
&lt;li&gt;SurfaceFlinger.cpp：这个类主要处理layer的合成，它合成好相关的layer后发送command给HW display进行进行显示；&lt;/li&gt;
&lt;li&gt;DispSyncSource：Vsync source 在Android系统中有两个instance，一是Vsync-app，另一个Vsync-sf。当SW-SYNC发生时，Vsyncsource会callback到其相应的EventThread，并且会在Systrace上显示出Vsync-sf和Vsync-app的跳变；&lt;/li&gt;
&lt;li&gt;EventThread.cpp：Vsync event处理线程，在系统中有两个EventThread，一个用于Vsync-app，另一个用于Vsync-sf。其记录App和SurfaceFlinger的requestnextVsync()请求，当SW-VSYNCevent触发时，EventThread线程通过BitTube通知App或SurfaceFlinger，App开始drawview，SurfaceFlinger 开始合成 dirty layer；&lt;/li&gt;
&lt;li&gt;MessageQueue.cpp：MessageQueue 主要处理surfaceflinger的Vsync请求和发生Vsync事件给surfaceFlinger；&lt;/li&gt;
&lt;li&gt;BitTube.cpp：Vsync 事件的传输通道。App或Surfaceflinger首先与EventThread建立DisplayEventConnection(EventThread::Connection::Connection,Connection 是BnDisplayEventConnection子类，BitTube是其dataChannel)。App或surfaceFlinger通过call DisplayEventConnection::requestNextVsync()(binder 通信)向EventThread请求Vsync event，当EventThread收到SW-VSYNCevent时，其通过BitTube把Vsync evnet发送给App或SufaceFlinger；&lt;/li&gt;
&lt;li&gt;BufferQueueProducer.cpp：在Vsync架构中，其主要作用是向EventThread请求Vsync-sfevent。当App画完一个frame后，其会把画完的buffer放到bufferqueue中通过call BufferQueueProducer::queueBuffer()，进而surfaceflinger进程会通过call DisplayEventConnection:: requestNextVsync()向EventThread请求Vsync event。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Vsyncevent产生的示意图如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%94%29----VSync%20%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/vsyncmake.jpg&quot; alt=&quot;vsync产生&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;App需要draw一个frame时，其会向EventThread(appEventThread)请求Vysncevent，当EventThread收到Vsync event时，EventThread通过BitTueb把Vsync event通知到App，同时跳变systrace中的Vsync-app。App收到Vsync-app，开始draw frame。当App画完一个frame后，把画好的内容放到bufferqueue中，就会要求一个Vsync-sf event，以便surfaceflinger在收到Vsync-sf event时合成相关的dirty的内容并通知DisplayHW。Display HW 会在下一个HWvsync时间点，把相关的内容更新到LCD上完成内容的更新。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;下面是其大概的流程图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%94%29----VSync%20%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/vsyncall.png&quot; alt=&quot;Vsync时序图&quot;&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;(SF-1)APP 画完一个frame以后,就会把其绘画的buffer放到buffer queue中.从生产者和消费者的关系来看,App是生产者,surfaceflinger进程是消费者.&lt;/li&gt;
&lt;li&gt;(SF-2)在SurfaceFlinger 进程内,当收到有更新的可用的frame时(需要render到LCD ),就会向EventThread请求Vsync event(requestNextVsync()).EventThread会记录下此请求,当下次Vsync event到来时,便会triggerVsync-sf event.&lt;/li&gt;
&lt;li&gt;DispSync 不断产生SW-VSYNCEVENT.当SW-VSYNCEVENT产生时,会检查是否有EventListener关心该event(SF和APP请求Vsync 时会在DispSync中创建EventListener并把其相应的DispSyncSource作为EventListener的callback),如有则调用EventListenercallback(DispSyncSource)的onDispSyncEvent.(callbacks[i].mCallback-&amp;gt;onDispSyncEvent(callbacks[i].mEventTime)).&lt;/li&gt;
&lt;li&gt;DispSyncSource会引起Vsync-sf或Vsync-app跳变,当onDispSyncEvent()被调用时,并且会直接调用EventThread的onVSyncEvent().&lt;/li&gt;
&lt;li&gt;EventThread会把Vsync-sf或Vsync-app event通知到App或surfaceFlinger当Vsync-sfevent产生时(callonDispSyncEvent),surfaceflinger进程合成dirty layer的内容(SF-5)并通知Display HW把相关的更新到LCD上.App则在Vsync-ap时开始drawview.&lt;/li&gt;
&lt;li&gt;Display HW 便会在HW 的vsync 到来时,更新LCD 的内容(SF-6).&lt;/li&gt;
&lt;li&gt;如果有Layer 的内容需要更新,surfaceflinger 便会把相关内容合成在一起,并且通知DisplayHW ,有相关的更新内容.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;程序实现&quot;&gt;&lt;a href=&quot;#程序实现&quot; class=&quot;headerlink&quot; title=&quot;程序实现&quot;&gt;&lt;/a&gt;程序实现&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们来看看其代码的实现，继续回到SurfaceFlinger.cpp中的init函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::init() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// start the EventThread&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;VSyncSource&amp;gt; vsyncSrc = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; DispSyncSource(&amp;amp;mPrimaryDispSync,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            vsyncPhaseOffsetNs, &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&quot;app&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEventThread = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; EventThread(vsyncSrc);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;VSyncSource&amp;gt; sfVsyncSrc = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; DispSyncSource(&amp;amp;mPrimaryDispSync,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sfVsyncPhaseOffsetNs, &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&quot;sf&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSFEventThread = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; EventThread(sfVsyncSrc);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEventQueue.setEventThread(mSFEventThread);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEventControlThread = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; EventControlThread(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEventControlThread-&amp;gt;run(&lt;span class=&quot;string&quot;&gt;&quot;EventControl&quot;&lt;/span&gt;, PRIORITY_URGENT_DISPLAY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// set a fake vsync period if there is no HWComposer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mHwc-&amp;gt;initCheck() != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mPrimaryDispSync.setPeriod(&lt;span class=&quot;number&quot;&gt;16666667&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当surfaceFlinger初始化时，其创建了两个DispSyncSource和两个EventThread，一个用于APP，而另一个用于SurfaceFlinger本身。我们知道DispSyncSource和DispSync协同工作，共同完成Vsyncevent的fire。而EventThread会trigger App draw frame和surfaceFlinger合成”dirty” layer在SW-VSYNCevent产生时。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%94%29----VSync%20%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/vsyncsf.jpg&quot; alt=&quot;vsyncsf&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面图形是Vsync信号从产生到驱动SF去工作的一个过程，其中绿色部分是HWC中的Vsync信号软件模拟进程，其他都是SF中的：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;其中包含4个线程，EventControlThread，就像是Vsync信号产生的闸刀，当然闸刀肯定需要人去打开和关闭，这个人就是SF；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;VsyncThread，下面的代码只介绍软件模拟的Vsync信号，这个线程主要工作就是循环定期产生信号，然后调用SF中的函数，这就相当于触发了；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;DispSyncThread，是Vsync信号的模型，VsyncThread首先触发DispSyncThread，然后DispSyncThread再去驱动其他事件，它就是Vsync在SF中的代表；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;EventThread，具体的事件线程，由DispSyncThread去驱动。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们接下来根据Vsync-sf先关分析一下流程。&lt;/p&gt;
&lt;h3 id=&quot;DispSync和DispSyncThread&quot;&gt;&lt;a href=&quot;#DispSync和DispSyncThread&quot; class=&quot;headerlink&quot; title=&quot;DispSync和DispSyncThread&quot;&gt;&lt;/a&gt;DispSync和DispSyncThread&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从上面SurfaceFlinger的init函数中，在构造DispSyncSource会传入一个mPrimaryDispSync的引用，它是SF类中有一个field为DispSync mPrimaryDispSync，因此在SF类创建时会在栈上生成这个对象。我们首先看看这个类的构造函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;DispSync::DispSync() :&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mRefreshSkipCount(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mThread(&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; DispSyncThread()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//创建DispSyncThread线程，并运行&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mThread-&amp;gt;run(&lt;span class=&quot;string&quot;&gt;&quot;DispSync&quot;&lt;/span&gt;, PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//清除一些变量为0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    reset();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    beginResync();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在DispSync 构造函数中，创建了DispSyncThread线程，并运行。DispSyncThread实现也位于DispSync.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;DispSyncThread():&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mStop(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mPeriod(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mPhase(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mWakeupLatency(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里面将mStop设置为false，mPeriod设置为0，还有其他的也置为0。因为DispSyncThread是Thread派生的，所以我们需要看看它的线程函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;threadLoop&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; now = systemTime(SYSTEM_TIME_MONOTONIC);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; nextEventTime = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Vector&amp;lt;CallbackInvocation&amp;gt; callbackInvocations;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; targetTime = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#123; &lt;span class=&quot;comment&quot;&gt;// Scope for lock&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mStop) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//false&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mPeriod == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//mCond阻塞，当signal，同时mPeriod 不为0时，继续往下执行，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                err = mCond.wait(mMutex);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;error waiting for new events: %s (%d)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            strerror(-err), err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//计算下一次vsync信号时间时间&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            nextEventTime = computeNextEventTimeLocked(now);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            targetTime = nextEventTime;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; isWakeup = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//如果还没到下一次vsync时间，则等待中间间隔时间&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (now &amp;lt; targetTime) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                err = mCond.waitRelative(mMutex, targetTime - now);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//等待超时，则唤醒&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == TIMED_OUT) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    isWakeup = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;error waiting for next event: %s (%d)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            strerror(-err), err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            now = systemTime(SYSTEM_TIME_MONOTONIC);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//唤醒触发&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (isWakeup) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//如果唤醒了，则计算Latency，如果Latency大于500000则强制Latency为500000&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mWakeupLatency = ((mWakeupLatency * &lt;span class=&quot;number&quot;&gt;63&lt;/span&gt;) +&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        (now - targetTime)) / &lt;span class=&quot;number&quot;&gt;64&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mWakeupLatency &amp;gt; &lt;span class=&quot;number&quot;&gt;500000&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// Don&#39;t correct by more than 500 us&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    mWakeupLatency = &lt;span class=&quot;number&quot;&gt;500000&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (kTraceDetailedInfo) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    ATRACE_INT64(&lt;span class=&quot;string&quot;&gt;&quot;DispSync:WakeupLat&quot;&lt;/span&gt;, now - nextEventTime);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    ATRACE_INT64(&lt;span class=&quot;string&quot;&gt;&quot;DispSync:AvgWakeupLat&quot;&lt;/span&gt;, mWakeupLatency);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//gatherCallbackInvocationsLocked函数获取本次VSync信号的回调函数列表&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//些回调函数是通过DispSync类的addEventListener函数加入的&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            callbackInvocations = gatherCallbackInvocationsLocked(now);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//接着就调用fireCallbackInvocations来依次调用列表中所有对象的onDispSyncEvent函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (callbackInvocations.size() &amp;gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            fireCallbackInvocations(callbackInvocations);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;DispSyncThread的threadLoop函数，主要这个函数比较计算时间来决定是否要发送信号。主要工作如下：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1. 模型线程DispSyncThread阻塞在mCond，等待别人给mPeriod 赋值和signal；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2. gatherCallbackInvocationsLocked函数获取本次VSync信号的回调函数列表，这些回调函数是通过DispSync类的addEventListener函数加入的；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3. 接着就调用fireCallbackInvocations来依次调用列表中所有对象的onDispSyncEvent函数。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;新建的DispSyncThread线程，目前被&lt;code&gt;阻塞&lt;/code&gt;&lt;/strong&gt;，先不管，我们先看模型DispSync和要驱动的事件(DispSyncSource，EventThread等)是如何联系起来的。&lt;/p&gt;
&lt;h3 id=&quot;DispSyncSource和EventThread&quot;&gt;&lt;a href=&quot;#DispSyncSource和EventThread&quot; class=&quot;headerlink&quot; title=&quot;DispSyncSource和EventThread&quot;&gt;&lt;/a&gt;DispSyncSource和EventThread&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在SF的init函数中，有如下代码，涉及到了DispSync，DispSyncSource，EventThread和mEventQueue的纠缠关系。我们可以看到在驱动事件DispSyncSource的构造中，我们输入了模型DispSync，这样就为回调创造了机会，下面看具体如何实现的。&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::init() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// start the EventThread&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//把模型mPrimaryDispSync(DispSync)保存在DispSyncSource中&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;VSyncSource&amp;gt; vsyncSrc = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; DispSyncSource(&amp;amp;mPrimaryDispSync,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            vsyncPhaseOffsetNs, &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&quot;app&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEventThread = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; EventThread(vsyncSrc);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;VSyncSource&amp;gt; sfVsyncSrc = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; DispSyncSource(&amp;amp;mPrimaryDispSync,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sfVsyncPhaseOffsetNs, &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&quot;sf&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSFEventThread = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; EventThread(sfVsyncSrc);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEventQueue.setEventThread(mSFEventThread);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个我们分布分析：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）先看下DispSyncSource对象的建立，其实这个对象从名字上看就是模型所驱动的事件。我们看看它的构造函数，也位于SurfaceFlinger.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;DispSyncSource(DispSync* dispSync, &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; phaseOffset, &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; traceVsync,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt;* label) :&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mValue(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mPhaseOffset(phaseOffset),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mTraceVsync(traceVsync),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mVsyncOnLabel(String8::format(&lt;span class=&quot;string&quot;&gt;&quot;VsyncOn-%s&quot;&lt;/span&gt;, label)),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mVsyncEventLabel(String8::format(&lt;span class=&quot;string&quot;&gt;&quot;VSYNC-%s&quot;&lt;/span&gt;, label)),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mDispSync(dispSync) &amp;#123;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;构造函数中主要设置了模型mDispSync(dispSync)，以及触发时间的偏移量mPhaseOffset(phaseOffset)。这个实参vsyncPhaseOffsetNs和sfVsyncPhaseOffsetNs定义如下，也位于SurfaceFlinger.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// This is the phase offset in nanoseconds of the software vsync event&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// relative to the vsync event reported by HWComposer.  The software vsync&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// event is when SurfaceFlinger and Choreographer-based applications run each&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// frame.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// This phase offset allows adjustment of the minimum latency from application&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// wake-up (by Choregographer) time to the time at which the resulting window&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// image is displayed.  This value may be either positive (after the HW vsync)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// or negative (before the HW vsync).  Setting it to 0 will result in a&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// minimum latency of two vsync periods because the app and SurfaceFlinger&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// will run just after the HW vsync.  Setting it to a positive number will&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// result in the minimum latency being:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//     (2 * VSYNC_PERIOD - (vsyncPhaseOffsetNs % VSYNC_PERIOD))&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// Note that reducing this latency makes it more likely for the applications&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// to not have their window content image ready in time.  When this happens&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// the latency will end up being an additional vsync period, and animations&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// will hiccup.  Therefore, this latency should be tuned somewhat&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// conservatively (or at least with awareness of the trade-off being made).&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int64_t&lt;/span&gt; vsyncPhaseOffsetNs = VSYNC_EVENT_PHASE_OFFSET_NS;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// This is the phase offset at which SurfaceFlinger&#39;s composition runs.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int64_t&lt;/span&gt; sfVsyncPhaseOffsetNs = SF_VSYNC_EVENT_PHASE_OFFSET_NS;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个phase就是用来调节vsync信号latency 时间，其定义我也是搜了整个工程才找到如下定义：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%94%29----VSync%20%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/phasecatch.png&quot; alt=&quot;phase&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;generic版本中phase-app为0，phase-sf为5000000。（不知道对不对=。=）&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）我们继续往下看，mSFEventThread = new EventThread(sfVsyncSrc);先看看EventThread的构造函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;EventThread::EventThread(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;VSyncSource&amp;gt;&amp;amp; src)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    : mVSyncSource(src),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mUseSoftwareVSync(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;span class=&quot;comment&quot;&gt;//软vsync初始为false&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mVsyncEnabled(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;span class=&quot;comment&quot;&gt;//vsync使能初始为false&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mDebugVsyncEnabled(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      mVsyncHintSent(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//i&amp;lt;2,只遍历主屏幕和扩展屏幕&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; i&amp;lt;DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mVSyncEvent[i].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mVSyncEvent[i].header.id = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mVSyncEvent[i].header.timestamp = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mVSyncEvent[i].vsync.count =  &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; sigevent se;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    se.sigev_notify = SIGEV_THREAD;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    se.sigev_value.sival_ptr = &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    se.sigev_notify_function = vsyncOffCallback;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    se.sigev_notify_attributes = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    timer_create(CLOCK_MONOTONIC, &amp;amp;se, &amp;amp;mTimerId);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;EventThread是Thread的派生类，还是RefBase的间接派生类，所以我们需要产看它的onFirstRef函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; EventThread::onFirstRef() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    run(&lt;span class=&quot;string&quot;&gt;&quot;EventThread&quot;&lt;/span&gt;, PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;将这个线程启动了起来，那么我们需要看下线程循环函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; EventThread::threadLoop() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    DisplayEventReceiver::Event event;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Vector&amp;lt; sp&amp;lt;EventThread::Connection&amp;gt; &amp;gt; signalConnections;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//等待事件到来&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    signalConnections = waitForEvent(&amp;amp;event);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// dispatch events to listeners...&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//把事件分发给listener&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; count = signalConnections.size();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; i&amp;lt;count ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;Connection&amp;gt;&amp;amp; conn(signalConnections[i]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// now see if we still need to report this event&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//然后调用每个连接的postEvent来发送Event&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = conn-&amp;gt;postEvent(event);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == -EAGAIN || err == -EWOULDBLOCK) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// The destination doesn&#39;t accept events anymore, it&#39;s probably&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// full. For now, we just drop the events on the floor.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;FIXME:&lt;/span&gt; Note that some events cannot be dropped and would have&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// to be re-sent later.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// Right-now we don&#39;t have the ability to do this.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ALOGW(&lt;span class=&quot;string&quot;&gt;&quot;EventThread: dropping event (%08x) for connection %p&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    event.header.type, conn.get());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// handle any other error on the pipe as fatal. the only&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// reasonable thing to do is to clean-up this connection.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// The most common error we&#39;ll get here is -EPIPE.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            removeDisplayEventConnection(signalConnections[i]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个线程函数里面主要做了三件事：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1. 调用waitForEvent等待事件到来；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2. 把事件分发给listener；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3. 然后调用每个连接的postEvent来发送Event。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们分部查看，先看看waitForEvent实现：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;96&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;97&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;98&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;99&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;100&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;101&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;102&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;103&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;104&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;105&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;106&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;107&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;108&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;109&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;110&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;111&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;112&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;113&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;114&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;115&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;116&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;117&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;118&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;119&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;120&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;121&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;122&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;123&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;124&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;125&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;126&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;127&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;128&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;129&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;130&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;131&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;132&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;133&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;134&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;135&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;136&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;137&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;138&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;139&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;140&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;     &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// This will return when (1) a vsync event has been received, and (2) there was&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// at least one connection interested in receiving it when we started waiting.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Vector&amp;lt; sp&amp;lt;EventThread::Connection&amp;gt; &amp;gt; EventThread::waitForEvent(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        DisplayEventReceiver::Event* event)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::Autolock _l(mLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Vector&amp;lt; sp&amp;lt;EventThread::Connection&amp;gt; &amp;gt; signalConnections;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;do&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; eventPending = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; waitForVSync = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; vsyncCount = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; timestamp = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//上面初始化EventThread时候，都是0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; i&amp;lt;DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            timestamp = mVSyncEvent[i].header.timestamp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (timestamp) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// we have a vsync event to dispatch&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                *event = mVSyncEvent[i];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mVSyncEvent[i].header.timestamp = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                vsyncCount = mVSyncEvent[i].vsync.count;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!timestamp) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// no vsync event, see if there are some other event&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            eventPending = !mPendingEvents.isEmpty();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (eventPending) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//初始时候为false&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// we have some other event to dispatch&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                *event = mPendingEvents[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mPendingEvents.removeAt(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// find out connections waiting for events&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//// 初始也是空的 SortedVector&amp;lt; wp&amp;lt;Connection&amp;gt; &amp;gt; mDisplayEventConnections;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; count = mDisplayEventConnections.size();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; i&amp;lt;count ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sp&amp;lt;Connection&amp;gt; connection(mDisplayEventConnections[i].promote());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (connection != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; added = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (connection-&amp;gt;count &amp;gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// we need vsync events because at least&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// one connection is waiting for it&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    waitForVSync = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (timestamp) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// we consume the event only if it&#39;s time&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// (ie: we received a vsync event)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (connection-&amp;gt;count == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            &lt;span class=&quot;comment&quot;&gt;// fired this time around&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            connection-&amp;gt;count = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            signalConnections.add(connection);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            added = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (connection-&amp;gt;count == &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt; ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                (vsyncCount % connection-&amp;gt;count) == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            &lt;span class=&quot;comment&quot;&gt;// continuous event, and time to report it&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            signalConnections.add(connection);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            added = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (eventPending &amp;amp;&amp;amp; !timestamp &amp;amp;&amp;amp; !added) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// we don&#39;t have a vsync event to process&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// (timestamp==0), but we have some pending&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// messages.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    signalConnections.add(connection);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// we couldn&#39;t promote this reference, the connection has&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// died, so clean-up!&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mDisplayEventConnections.removeAt(i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                --i; --count;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Here we figure out if we need to enable or disable vsyncs&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (timestamp &amp;amp;&amp;amp; !waitForVSync) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// we received a VSYNC but we have no clients&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// don&#39;t report it, and disable VSYNC events&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disableVSyncLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!timestamp &amp;amp;&amp;amp; waitForVSync) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// we have at least one client, so we want vsync enabled&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// (&lt;span class=&quot;doctag&quot;&gt;TODO:&lt;/span&gt; this function is called right after we finish&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// notifying clients of a vsync, so this call will be made&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// at the vsync rate, e.g. 60fps.  If we can accurately&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// track the current state we could avoid making this call&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// so often.)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            enableVSyncLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// note: !timestamp implies signalConnections.isEmpty(), because we&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// don&#39;t populate signalConnections if there&#39;s no vsync pending&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!timestamp &amp;amp;&amp;amp; !eventPending) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// wait for something to happen&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (waitForVSync) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// This is where we spend most of our time, waiting&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// for vsync events and new client registrations.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// If the screen is off, we can&#39;t use h/w vsync, so we&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// use a 16ms timeout instead.  It doesn&#39;t need to be&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// precise, we just need to keep feeding our clients.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// We don&#39;t want to stall if there&#39;s a driver bug, so we&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// use a (long) timeout when waiting for h/w vsync, and&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// generate fake events when necessary.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; softwareSync = mUseSoftwareVSync;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; timeout = softwareSync ? ms2ns(&lt;span class=&quot;number&quot;&gt;16&lt;/span&gt;) : ms2ns(&lt;span class=&quot;number&quot;&gt;1000&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mCondition.waitRelative(mLock, timeout) == TIMED_OUT) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!softwareSync) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        ALOGW(&lt;span class=&quot;string&quot;&gt;&quot;Timed out waiting for hw vsync; faking it&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;FIXME:&lt;/span&gt; how do we decide which display id the fake&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// vsync came from ?&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    mVSyncEvent[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    mVSyncEvent[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].header.id = DisplayDevice::DISPLAY_PRIMARY;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    mVSyncEvent[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    mVSyncEvent[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].vsync.count++;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// Nobody is interested in vsync, so we just want to sleep.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// h/w vsync should be disabled, so this will wait until we&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// get a new connection, or an existing connection becomes&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// interested in receiving vsync again.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//所以EventThread初始的时候会在这阻塞&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mCondition.wait(mLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (signalConnections.isEmpty());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//因为mCondition有可能异常返回，所以要看下这个while，就知道何时mCondition被正常的signal&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果signalConnections不为空了，这时候就会从while中退出来&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//也就是上面的mDisplayEventConnections有东西了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// here we&#39;re guaranteed to have a timestamp and some connections to signal&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// (The connections might have dropped out of mDisplayEventConnections&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// while we were asleep, but we&#39;ll still have strong references to them.)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; signalConnections;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;waitForEvent函数中下面代码段，timestamp为0表示没有时间，waitForSync为true表示至少有一个客户和EventThread建立了连接。这段代码一旦有客户连接，就调用enableVSyncLocked接收DispSyncSource的VSync信号。如果在接受信号中，所有客户都断开了连接，则调用disableVSyncLocked函数停止接受DispSyncSource对象的信号。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;虽然代码量有些多，但是我们是初始化时候，所以省去了很多判断逻辑。&lt;/strong&gt;因此主要工作就不多了，主要如下：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;①初始的时候，mCondition会阻塞；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;② 因为mCondition有可能异常返回，所以要看下外围的while循环，就知道何时mCondition会被signal。即使mCondition异常返回，也会再去判断signalConnections是否为空。空的话继续阻塞，如果signalConnections不为空了，这时候就会从while中退出来，也就是上面的mDisplayEventConnections有东西了。所以mDisplayEventConnections需要留意何时赋值啦。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;至此，&lt;strong&gt;创建了一个mSFEventThread = new EventThread(sfVsyncSrc);，也&lt;code&gt;阻塞&lt;/code&gt;着了&lt;/strong&gt;。。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;至于下面的 2. 把事件分发给listener；3. 然后调用每个连接的postEvent来发送Event。这两个步骤我们下面会讲到，这里先不看它。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）从上面得知在DsipSync里面创建的DispSyncThread线程阻塞等待着；还有上面的EventThread线程，也阻塞等待了。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;下面我们继续看mEventQueue.setEventThread(mSFEventThread);会不会解除阻塞。这里EventThread和SF主线程的MessageQueue又纠缠到了一起：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; MessageQueue::setEventThread(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;EventThread&amp;gt;&amp;amp; eventThread)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEventThread = eventThread;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//SF与EventThread建立连接&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEvents = eventThread-&amp;gt;createEventConnection();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//创建通信通道&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEventTube = mEvents-&amp;gt;getDataChannel();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//Looper连接通道，进行消息循环&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mLooper-&amp;gt;addFd(mEventTube-&amp;gt;getFd(), &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, Looper::EVENT_INPUT,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            MessageQueue::cb_eventReceiver, &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们依然分部查看：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1. 首先， eventThread-&amp;gt;createEventConnection()，新建了一个Connection对象：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sp&amp;lt;EventThread::Connection&amp;gt; EventThread::createEventConnection() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Connection(&lt;span class=&quot;keyword&quot;&gt;const_cast&lt;/span&gt;&amp;lt;EventThread*&amp;gt;(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Connection对象如下图所示:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%94%29----VSync%20%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/Connection.jpg&quot; alt=&quot;Connection&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Connection中保存了了一个EventThread对象，和一个生成的BitTube对象mChannel，下面看下Connection的构造函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;EventThread::Connection::Connection(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;EventThread&amp;gt;&amp;amp; eventThread)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    : count(&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;), mEventThread(eventThread), mChannel(&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; BitTube())&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;调用了BitTube的无参构造函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;BitTube::BitTube()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    : mSendFd(&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;), mReceiveFd(&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    init(DEFAULT_SOCKET_BUFFER_SIZE, DEFAULT_SOCKET_BUFFER_SIZE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;构造函数里调用了init函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; BitTube::init(&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; rcvbuf, &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; sndbuf) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; sockets[&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (socketpair(AF_UNIX, SOCK_SEQPACKET, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, sockets) == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; size = DEFAULT_SOCKET_BUFFER_SIZE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        setsockopt(sockets[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;], SOL_SOCKET, SO_RCVBUF, &amp;amp;rcvbuf, &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(rcvbuf));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        setsockopt(sockets[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;], SOL_SOCKET, SO_SNDBUF, &amp;amp;sndbuf, &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(sndbuf));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// sine we don&#39;t use the &quot;return channel&quot;, we keep it small...&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        setsockopt(sockets[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;], SOL_SOCKET, SO_SNDBUF, &amp;amp;size, &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(size));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        setsockopt(sockets[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;], SOL_SOCKET, SO_RCVBUF, &amp;amp;size, &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(size));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        fcntl(sockets[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;], F_SETFL, O_NONBLOCK);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        fcntl(sockets[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;], F_SETFL, O_NONBLOCK);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mReceiveFd = sockets[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSendFd = sockets[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mReceiveFd = -errno;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;BitTube: pipe creation failed (%s)&quot;&lt;/span&gt;, strerror(-mReceiveFd));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;建立一个域套接字，用fcntl设置成非阻塞模式，然后两个fd，一个读一个写，mSendFd和mReceiveFd。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们上面创建一个Connection，但是又是一个sp指针，所以就得看看它的onFirstRef函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; EventThread::Connection::onFirstRef() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;NOTE:&lt;/span&gt; mEventThread doesn&#39;t hold a strong reference on us&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEventThread-&amp;gt;registerDisplayEventConnection(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里又调用EventThread的registerDisplayEventConnection函数，我们继续查看：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; EventThread::registerDisplayEventConnection(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;EventThread::Connection&amp;gt;&amp;amp; connection) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::Autolock _l(mLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//把connection添加到mDisplayEventConnections&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDisplayEventConnections.add(connection);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//mCondition解除&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCondition.broadcast();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;前面提到，EventThread一直阻塞在waitForEvent中，正是这个mCondition，这里也对mDisplayEventConnections添加了东西，不为空了。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;为了方便分析，我们再把前面的waitForEvent函数列出来，这次就是另一套逻辑了：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;96&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;97&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;98&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;99&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;100&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;101&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;102&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;103&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;104&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;105&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;106&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;107&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;108&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;109&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;110&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;111&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;112&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;113&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;114&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;115&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;116&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;117&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;118&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;119&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;120&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;121&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;122&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;123&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;124&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;125&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;126&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;127&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;128&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;129&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;130&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;131&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;132&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;133&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;134&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;135&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;136&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// This will return when (1) a vsync event has been received, and (2) there was&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// at least one connection interested in receiving it when we started waiting.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Vector&amp;lt; sp&amp;lt;EventThread::Connection&amp;gt; &amp;gt; EventThread::waitForEvent(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        DisplayEventReceiver::Event* event)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::Autolock _l(mLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Vector&amp;lt; sp&amp;lt;EventThread::Connection&amp;gt; &amp;gt; signalConnections;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;do&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; eventPending = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; waitForVSync = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; vsyncCount = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; timestamp = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; i&amp;lt;DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            timestamp = mVSyncEvent[i].header.timestamp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (timestamp) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// we have a vsync event to dispatch&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                *event = mVSyncEvent[i];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mVSyncEvent[i].header.timestamp = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                vsyncCount = mVSyncEvent[i].vsync.count;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!timestamp) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//这次这里还是0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// no vsync event, see if there are some other event&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            eventPending = !mPendingEvents.isEmpty();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (eventPending) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// we have some other event to dispatch&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                *event = mPendingEvents[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mPendingEvents.removeAt(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// find out connections waiting for events&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//有东西了，就是保存的Connection&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; count = mDisplayEventConnections.size();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; i&amp;lt;count ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sp&amp;lt;Connection&amp;gt; connection(mDisplayEventConnections[i].promote());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (connection != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; added = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (connection-&amp;gt;count &amp;gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// we need vsync events because at least&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// one connection is waiting for it&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    waitForVSync = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (timestamp) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// we consume the event only if it&#39;s time&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// (ie: we received a vsync event)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (connection-&amp;gt;count == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            &lt;span class=&quot;comment&quot;&gt;// fired this time around&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            connection-&amp;gt;count = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            signalConnections.add(connection);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            added = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (connection-&amp;gt;count == &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt; ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                (vsyncCount % connection-&amp;gt;count) == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            &lt;span class=&quot;comment&quot;&gt;// continuous event, and time to report it&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            signalConnections.add(connection);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            added = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (eventPending &amp;amp;&amp;amp; !timestamp &amp;amp;&amp;amp; !added) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// we don&#39;t have a vsync event to process&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// (timestamp==0), but we have some pending&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// messages.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    signalConnections.add(connection);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// we couldn&#39;t promote this reference, the connection has&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// died, so clean-up!&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mDisplayEventConnections.removeAt(i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                --i; --count;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Here we figure out if we need to enable or disable vsyncs&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (timestamp &amp;amp;&amp;amp; !waitForVSync) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//0 true&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// we received a VSYNC but we have no clients&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// don&#39;t report it, and disable VSYNC events&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            disableVSyncLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!timestamp &amp;amp;&amp;amp; waitForVSync) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//所以走到了这里&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// we have at least one client, so we want vsync enabled&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// (&lt;span class=&quot;doctag&quot;&gt;TODO:&lt;/span&gt; this function is called right after we finish&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// notifying clients of a vsync, so this call will be made&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// at the vsync rate, e.g. 60fps.  If we can accurately&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// track the current state we could avoid making this call&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// so often.)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//这次走到了这里&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            enableVSyncLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// note: !timestamp implies signalConnections.isEmpty(), because we&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// don&#39;t populate signalConnections if there&#39;s no vsync pending&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!timestamp &amp;amp;&amp;amp; !eventPending) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//0 false&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// wait for something to happen&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (waitForVSync) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//true&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// This is where we spend most of our time, waiting&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// for vsync events and new client registrations.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// If the screen is off, we can&#39;t use h/w vsync, so we&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// use a 16ms timeout instead.  It doesn&#39;t need to be&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// precise, we just need to keep feeding our clients.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// We don&#39;t want to stall if there&#39;s a driver bug, so we&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// use a (long) timeout when waiting for h/w vsync, and&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// generate fake events when necessary.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; softwareSync = mUseSoftwareVSync;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; timeout = softwareSync ? ms2ns(&lt;span class=&quot;number&quot;&gt;16&lt;/span&gt;) : ms2ns(&lt;span class=&quot;number&quot;&gt;1000&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mCondition.waitRelative(mLock, timeout) == TIMED_OUT) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!softwareSync) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        ALOGW(&lt;span class=&quot;string&quot;&gt;&quot;Timed out waiting for hw vsync; faking it&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;FIXME:&lt;/span&gt; how do we decide which display id the fake&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;// vsync came from ?&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    mVSyncEvent[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    mVSyncEvent[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].header.id = DisplayDevice::DISPLAY_PRIMARY;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    mVSyncEvent[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    mVSyncEvent[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].vsync.count++;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// Nobody is interested in vsync, so we just want to sleep.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// h/w vsync should be disabled, so this will wait until we&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// get a new connection, or an existing connection becomes&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// interested in receiving vsync again.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mCondition.wait(mLock);&lt;span class=&quot;comment&quot;&gt;//这个之前的wait已经解开了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (signalConnections.isEmpty());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// here we&#39;re guaranteed to have a timestamp and some connections to signal&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// (The connections might have dropped out of mDisplayEventConnections&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// while we were asleep, but we&#39;ll still have strong references to them.)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; signalConnections;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以在waitEvent里，这次的逻辑和上次不同了，主要是一下几点：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;①建立Connection后，mCondition返回了；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;②这里timestamp 还是0 ;&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;③mDisplayEventConnections非空了，将waitForVSync = true;&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;④所以会执行到enableVSyncLocked();。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;那么我们看看enableVSyncLocked函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; EventThread::enableVSyncLocked() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mUseSoftwareVSync) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//false&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// never enable h/w VSYNC when screen is off&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mVsyncEnabled) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//false&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mVsyncEnabled = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;span class=&quot;comment&quot;&gt;//将mVsyncEnabled 置为true&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//DispSyncSource的setCallback，把mCallback设置为EventThread&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mVSyncSource-&amp;gt;setCallback(&lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;VSyncSource::Callback*&amp;gt;(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//调用DispSyncSource的setVSyncEnabled&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mVSyncSource-&amp;gt;setVSyncEnabled(&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDebugVsyncEnabled = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sendVsyncHintOnLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个也分两步：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;①将mVsyncEnabled 设为true，调用mVSyncSource-&amp;gt;setCallback(static_cast&lt;vsyncsource::callback*&gt;(this));，this为EventThread，既是调用DispSyncSource的setCallback，把mCallback设置为EventThread：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;setCallback&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;VSyncSource::Callback&amp;gt;&amp;amp; callback)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCallback = callback;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/vsyncsource::callback*&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;②调用mVSyncSource-&amp;gt;setVSyncEnabled(true);，既是调用DispSyncSource的setVSyncEnabled：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;setVSyncEnabled&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; enable)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;span class=&quot;comment&quot;&gt;//true&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Do NOT lock the mutex here so as to avoid any mutex ordering issues&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// with locking it in the onDispSyncEvent callback.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (enable) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;////在硬件模型mDispSync中添加addEventListener，一个参数为偏移量，一个为DispSyncSource&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = mDispSync-&amp;gt;addEventListener(mPhaseOffset,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;DispSync::Callback*&amp;gt;(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;error registering vsync callback: %s (%d)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    strerror(-err), err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//ATRACE_INT(mVsyncOnLabel.string(), 1);&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = mDispSync-&amp;gt;removeEventListener(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;DispSync::Callback*&amp;gt;(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;error unregistering vsync callback: %s (%d)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    strerror(-err), err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//ATRACE_INT(mVsyncOnLabel.string(), 0);&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从上面的代码可以看出，这里是将驱动事件DispSyncSource和硬件模型mDispSync建立起关系。既然调用了DispSync的addEventListener，那么我们就继续查看：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//DispSync的addEventListener&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; DispSync::addEventListener(&lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; phase,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;Callback&amp;gt;&amp;amp; callback) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mThread-&amp;gt;addEventListener(phase, callback);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//DispSyncThread的addEventListener&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; addEventListener(&lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; phase, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;DispSync::Callback&amp;gt;&amp;amp; callback) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; mEventListeners.size(); i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mEventListeners[i].mCallback == callback) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; BAD_VALUE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        EventListener listener;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        listener.mPhase = phase;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        listener.mCallback = callback;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// We want to allow the firstmost future event to fire without&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// allowing any past events to fire.  Because&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// computeListenerNextEventTimeLocked filters out events within a half&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// a period of the last event time, we need to initialize the last&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// event time to a half a period in the past.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        listener.mLastEventTime = systemTime(SYSTEM_TIME_MONOTONIC) - mPeriod / &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;////把listener放到mEventListeners中&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mEventListeners.push(listener);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;////释放mCond&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mCond.signal();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里可以看出，驱动事件DispSyncSource是硬件模型DispSync的“listener”，监听者，把两者联系了起来。并把DispSyncThread线程中的阻塞mCond解除，但是，前面我们分析过，还要mPeriod 非0。我们可以回顾一下上面的代码片段，DispSyncThread的threadLoop函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;threadLoop&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt;(&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;)&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mPeriod == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    err = mCond.wait(mMutex);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;error waiting for new events: %s (%d)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                strerror(-err), err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;那么哪里给mPeriod 赋值呢？我们上面讲EventControlThread闸刀控制线程的时候，initializeDisplays()函数会被调用，最终会调用resyncToHardwareVsync函数，这个里面会获取mPeriod屏幕刷新率，然后给mPeriod 赋值：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::resyncToHardwareVsync(&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; makeAvailable) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; period =&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mPrimaryDispSync.reset();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mPrimaryDispSync.setPeriod(period);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后调用DispSync的setPeriod函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; DispSync::setPeriod(&lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; period) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mPeriod = period;&lt;span class=&quot;comment&quot;&gt;//mPeriod 赋值后，已经不为0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mPhase = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//调用线程的更新模型函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mThread-&amp;gt;updateModel(mPeriod, mPhase);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;mPeriod 赋值后，已经不为0；然后调用线程的更新模型函数updateModel：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;updateModel&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; period, &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; phase)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mPeriod = period;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mPhase = phase;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//mCond阻塞解除&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCond.signal();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;至此，DispSync中设置了监听者DispSyncSource，mPeriod 也不为0，硬件模型线程不再阻塞，不阻塞就会去处理vsync事件，这个我们后面会讲。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;经过调用mEvents = eventThread-&amp;gt;createEventConnection();完成了一下几个功能：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;①MessageQueue中保存了一个Connection，mEvents ；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;②EventThread中保存了这个Connection，mDisplayEventConnections.add(connection);&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;③mVSyncSource-&amp;gt;setCallback 把mCallback = callback 设置为EventThread；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;④在mDispSync中注册listener， 放到DispSyncthread的mEventListeners中，这个listener的callback就是mVSyncSource。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2. 然后就是创建通信通道。接着继续MessageQueue::setEventThread()函数，调用mEventTube = mEvents-&amp;gt;getDataChannel()。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;mEvents类型为sp&amp;lt; IDisplayEventConnection &amp;gt; ;在上一步mEvents = eventThread-&amp;gt;createEventConnection();返回的直接是Connection对象。Connection继承于BnDisplayEventConnection，BnDisplayEventConnection继承于BnInterface&amp;lt; IDisplayEventConnection &amp;gt;。因此我们找到bp端的getDataChannel函数，位于BpDisplayEventConnection类当中，继承于BpInterface&amp;lt; IDisplayEventConnection &amp;gt;位于frameworks/native/libs/gui/IDisplayEventConnection.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; sp&amp;lt;BitTube&amp;gt; getDataChannel() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Parcel data, reply;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    remote()-&amp;gt;transact(GET_DATA_CHANNEL, data, &amp;amp;reply);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; BitTube(reply);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;相应的bn端位onTransact方法于也位于IDisplayEventConnection.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; BnDisplayEventConnection::onTransact(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; code, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Parcel&amp;amp; data, Parcel* reply, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt;(code) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; GET_DATA_CHANNEL: &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            CHECK_INTERFACE(IDisplayEventConnection, data, reply);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sp&amp;lt;BitTube&amp;gt; channel(getDataChannel());&lt;span class=&quot;comment&quot;&gt;//这个getDataChannel是Connection类的函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            channel-&amp;gt;writeToParcel(reply);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; BBinder::onTransact(code, data, reply, flags);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面那个getDataChannel是Connection类的函数，我们看看Connection的getDataChannel函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sp&amp;lt;BitTube&amp;gt; EventThread::Connection::getDataChannel() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mChannel;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;mChannel就是我们在构造函数里面的new BitTube()。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这样mEventTube 中只包含了读fd，而mEvents这个connection中的mChannel只剩下写fd，两个依然是一对读写，，但是分开了，如下图所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%94%29----VSync%20%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/ConnectionTube.jpg&quot; alt=&quot;ConnectionTube&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3.  继续调用，这里就是把mEventTube这个读tube注册到SF主线程的Looper中去，回调函数为MessageQueue::cb_eventReceiver：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;mLooper-&amp;gt;addFd(mEventTube-&amp;gt;getFd(), &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, ALOOPER_EVENT_INPUT,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            MessageQueue::cb_eventReceiver, &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里用到了&lt;a href=&quot;http://windrunnerlihuan.com/2016/07/31/Android%E6%B6%88%E6%81%AF%E6%9C%BA%E5%88%B6%E9%9B%B6%E6%95%A3%E5%88%86%E6%9E%90/&quot;&gt;Android消息处理零散分析&lt;/a&gt;的内容，如果忘记了，可以翻一翻。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;因为注册了回调事件，因此我们需要查看MessageQueue::cb_eventReceiver函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; MessageQueue::cb_eventReceiver(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; fd, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; events, &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;* data) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    MessageQueue* &lt;span class=&quot;built_in&quot;&gt;queue&lt;/span&gt; = &lt;span class=&quot;keyword&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;MessageQueue *&amp;gt;(data);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;built_in&quot;&gt;queue&lt;/span&gt;-&amp;gt;eventReceiver(fd, events);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后是eventReceiver函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; MessageQueue::eventReceiver(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;comment&quot;&gt;/*fd*/&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;comment&quot;&gt;/*events*/&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;ssize_t&lt;/span&gt; n;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    DisplayEventReceiver::Event buffer[&lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, &lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;)) &amp;gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; i&amp;lt;n ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; INVALIDATE_ON_VSYNC &lt;span class=&quot;comment&quot;&gt;//1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mHandler-&amp;gt;dispatchInvalidate();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;else&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mHandler-&amp;gt;dispatchRefresh();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里会从MessageQueue的读BitTube中读出event，然后调用mHandler-&amp;gt;dispatchInvalidate():&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; MessageQueue::Handler::dispatchInvalidate() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((android_atomic_or(eventMaskInvalidate, &amp;amp;mEventMask) &amp;amp; eventMaskInvalidate) == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mQueue.mLooper-&amp;gt;sendMessage(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;, Message(MessageQueue::INVALIDATE));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接收消息就是handleMessage函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; MessageQueue::Handler::handleMessage(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Message&amp;amp; message) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt; (message.what) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; INVALIDATE:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            android_atomic_and(~eventMaskInvalidate, &amp;amp;mEventMask);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mQueue.mFlinger-&amp;gt;onMessageReceived(message.what);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; REFRESH:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            android_atomic_and(~eventMaskRefresh, &amp;amp;mEventMask);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mQueue.mFlinger-&amp;gt;onMessageReceived(message.what);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; TRANSACTION:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            android_atomic_and(~eventMaskTransaction, &amp;amp;mEventMask);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mQueue.mFlinger-&amp;gt;onMessageReceived(message.what);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;进而去调用SF的onMessageReceived函数，最终每次Vsync信号来了，SF都会去执行handleMessageTransaction()等函数。&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::onMessageReceived(&lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; what) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt; (what) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; MessageQueue::TRANSACTION:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        handleMessageTransaction();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; MessageQueue::INVALIDATE:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        handleMessageTransaction();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        handleMessageInvalidate();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        signalRefresh();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; MessageQueue::REFRESH:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        handleMessageRefresh();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;至此我们对于vsync消息的准备逻辑工作都做完了。但是细心的读者应该发现了，我们还没有按正常流程处理一遍vsync信号，就是当vsync产生后，SurfaceFlinger的回调函数onVSyncReceived处理过程。接下来我们就分析一下这个过程。&lt;/p&gt;
&lt;h1 id=&quot;VSync信号处理&quot;&gt;&lt;a href=&quot;#VSync信号处理&quot; class=&quot;headerlink&quot; title=&quot;VSync信号处理&quot;&gt;&lt;/a&gt;VSync信号处理&lt;/h1&gt;&lt;h2 id=&quot;矫正VSync时间&quot;&gt;&lt;a href=&quot;#矫正VSync时间&quot; class=&quot;headerlink&quot; title=&quot;矫正VSync时间&quot;&gt;&lt;/a&gt;矫正VSync时间&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们再次借助上面那幅Vsync event产生的示意图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%94%29----VSync%20%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/vsyncmake.jpg&quot; alt=&quot;Vsync时序图&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里HW_VSYNC就是HW_VSYNC_0。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当SF从HWComposer收到VSYNC(HW_VSYNC_0)时，会调用onVSyncReceived函数处理：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::onVSyncReceived(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; type, &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; timestamp) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; needsHwVsync = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123; &lt;span class=&quot;comment&quot;&gt;// Scope for the lock&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Mutex::Autolock _l(mHWVsyncLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (type == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; &amp;amp;&amp;amp; mPrimaryHWVsyncEnabled) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//将新的VSYNC时间交给DispSync&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (needsHwVsync) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//是否还需要vsync&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        enableHardwareVsync();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        disableHardwareVsync(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;它会利用DispSync::addResyncSample将新的VSYNC时间交给DispSync。addResyncSample决定是否还需要HW_VSYNC的输入,如果不需要,就会将HW_VSYNC关掉。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后我们继续查看DispSync::addResyncSample：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; DispSync::addResyncSample(&lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; timestamp) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//MAX_RESYNC_SAMPLES = 32&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mResyncSamples[idx] = timestamp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mNumResyncSamples &amp;lt; MAX_RESYNC_SAMPLES) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mNumResyncSamples++;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mFirstResyncSample = (mFirstResyncSample + &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;) % MAX_RESYNC_SAMPLES;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//这个函数很重要，用来计算SW_VSYNC的值，直到误差小于threshold&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    updateModelLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//MAX_RESYNC_SAMPLES_WITHOUT_PRESENT = 12&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mNumResyncSamplesSincePresent++ &amp;gt; MAX_RESYNC_SAMPLES_WITHOUT_PRESENT) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        resetErrorLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (kIgnorePresentFences) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// If we don&#39;t have the sync framework we will never have&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// addPresentFence called.  This means we have no way to know whether&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// or not we&#39;re synchronized with the HW vsyncs, so we just request&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// that the HW vsync events be turned on whenever we need to generate&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// SW vsync events.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mThread-&amp;gt;hasAnyEventListeners();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mPeriod == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; || mError &amp;gt; kErrorThreshold;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;DispSync是利用HW_VSYNC和PresentFence来判断是否需要开启HW_VSYNC。HW_VSYNC最少要3个，最多是32个，实际上要用几个则不一定，DispSync拿到3个HW_VSYNC后就会计算出SW_VSYNC，只要收到的PresentFence没有超过误差，则HW_VSYNC就会关掉，以便节省功耗.不然会继续开启HW_VSYNC计算SW_VSYNC的值，直到误差小于threshold。其计算的方法是DispSync::updateModelLocked()：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; DispSync::updateModelLocked() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mNumResyncSamples &amp;gt;= MIN_RESYNC_SAMPLES_FOR_UPDATE) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; durationSum = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;; i &amp;lt; mNumResyncSamples; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; prev = (idx + MAX_RESYNC_SAMPLES - &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;) % MAX_RESYNC_SAMPLES;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            durationSum += mResyncSamples[idx] - mResyncSamples[prev];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mPeriod = durationSum / (mNumResyncSamples - &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;double&lt;/span&gt; sampleAvgX = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;double&lt;/span&gt; sampleAvgY = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;double&lt;/span&gt; scale = &lt;span class=&quot;number&quot;&gt;2.0&lt;/span&gt; * M_PI / &lt;span class=&quot;keyword&quot;&gt;double&lt;/span&gt;(mPeriod);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; mNumResyncSamples; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; sample = mResyncSamples[idx];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;double&lt;/span&gt; samplePhase = &lt;span class=&quot;keyword&quot;&gt;double&lt;/span&gt;(sample % mPeriod) * scale;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sampleAvgX += &lt;span class=&quot;built_in&quot;&gt;cos&lt;/span&gt;(samplePhase);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sampleAvgY += &lt;span class=&quot;built_in&quot;&gt;sin&lt;/span&gt;(samplePhase);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sampleAvgX /= &lt;span class=&quot;keyword&quot;&gt;double&lt;/span&gt;(mNumResyncSamples);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sampleAvgY /= &lt;span class=&quot;keyword&quot;&gt;double&lt;/span&gt;(mNumResyncSamples);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mPhase = &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt;(&lt;span class=&quot;built_in&quot;&gt;atan2&lt;/span&gt;(sampleAvgY, sampleAvgX) / scale);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mPhase &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mPhase += mPeriod;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (kTraceDetailedInfo) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ATRACE_INT64(&lt;span class=&quot;string&quot;&gt;&quot;DispSync:Period&quot;&lt;/span&gt;, mPeriod);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ATRACE_INT64(&lt;span class=&quot;string&quot;&gt;&quot;DispSync:Phase&quot;&lt;/span&gt;, mPhase);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Artificially inflate the period if requested.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mPeriod += mPeriod * mRefreshSkipCount;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mThread-&amp;gt;updateModel(mPeriod, mPhase);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;基本思想如下:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;计算目前收到HW_VSYNC间隔,取平均值(AvgPeriod) HW_VSYNC;&lt;/li&gt;
&lt;li&gt;将每个收到的VSYNC时间与AvgPeriod算出误差. (Delta = Time %AvgPeriod);&lt;/li&gt;
&lt;li&gt;将Delta转换成角度(DeltaPhase),如果AvgPeriod是360度,DeltaPhase = 2&lt;em&gt;PI&lt;/em&gt;Delta/AvgPeriod;&lt;/li&gt;
&lt;li&gt;从DeltaPhase可以得到DeltaX与DeltaY (DeltaX =cos(DeltaPhase), DeltaY = sin(DeltaPhase));&lt;/li&gt;
&lt;li&gt;将每个收到的VSYNC的DeltaX与DeltaY取平均,可以得到AvgX与AvgY;&lt;/li&gt;
&lt;li&gt;利用atan与AvgX, AvgY可以得到平圴的phase (AvgPhase);&lt;/li&gt;
&lt;li&gt;AvgPeriod + AvgPhase就是SW_VSYNC。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%94%29----VSync%20%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/updatemodel.png&quot; alt=&quot;updatemodel&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当DispSync收到addPresentFence时(最多记录8个sample)，每一个fence的时间算出(Time% AvgPeriod)的平方当作误差，将所有的Fence误差加总起来如果大于某个Threshold，就表示需要校正(DispSync::updateErrorLocked)。校正的方法是呼叫DispSync::beginResync()将所有的HW_VSYNC清掉,开启HW_VSYNC。等至少3个HW_VSYNC再重新计算。&lt;/p&gt;
&lt;h2 id=&quot;处理VSync消息&quot;&gt;&lt;a href=&quot;#处理VSync消息&quot; class=&quot;headerlink&quot; title=&quot;处理VSync消息&quot;&gt;&lt;/a&gt;处理VSync消息&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;消息处理流程依然需要分步骤：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）我们继续回到DispSync的threadLoop函数中，回顾上面的内容，因为在这里我们需要搜集vsync触发事件：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;threadLoop&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Vector&amp;lt;CallbackInvocation&amp;gt; callbackInvocations;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            callbackInvocations = gatherCallbackInvocationsLocked(now);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (callbackInvocations.size() &amp;gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                fireCallbackInvocations(callbackInvocations);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;mPeriod 不为0，也有signal，DispSyncThread线程不阻塞了，执行gatherCallbackInvocationsLocked(now)和fireCallbackInvocations(callbackInvocations)。我们先查看gatherCallbackInvocationsLocked函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;Vector&amp;lt;CallbackInvocation&amp;gt; gatherCallbackInvocationsLocked(&lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; now) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Vector&amp;lt;CallbackInvocation&amp;gt; callbackInvocations;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; ref = now - mPeriod;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//这里的mEventListeners[i].mCallback都是驱动的事件DispSyncSource&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; mEventListeners.size(); i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; t = computeListenerNextEventTimeLocked(mEventListeners[i],&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ref);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (t &amp;lt; now) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            CallbackInvocation ci;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ci.mCallback = mEventListeners[i].mCallback;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ci.mEventTime = t;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            callbackInvocations.push(ci);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mEventListeners.editItemAt(i).mLastEventTime = t;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; callbackInvocations;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后发送事件，fireCallbackInvocations函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;fireCallbackInvocations&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Vector&amp;lt;CallbackInvocation&amp;gt;&amp;amp; callbacks)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; callbacks.size(); i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//这里的callbacks[i].mCallback，就是驱动的事件DispSyncSource&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        callbacks[i].mCallback-&amp;gt;onDispSyncEvent(callbacks[i].mEventTime);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里会回调DispSyncSource的onDispSyncEvent函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;onDispSyncEvent&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; when)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;VSyncSource::Callback&amp;gt; callback;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mMutex)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        callback = mCallback;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mTraceVsync) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mValue = (mValue + &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;) % &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ATRACE_INT(mVsyncEventLabel.&lt;span class=&quot;built_in&quot;&gt;string&lt;/span&gt;(), mValue);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;////这里的callback为EventThread&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (callback != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        callback-&amp;gt;onVSyncEvent(when);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;继续调用，这里已经从驱动事件，转化到驱动事件的线程EventThread中，填充EventThread的mVSyncEvent，因此我们查看onVSyncEvent函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; EventThread::onVSyncEvent(&lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; timestamp) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::Autolock _l(mLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mVSyncEvent[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mVSyncEvent[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].header.id = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mVSyncEvent[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].header.timestamp = timestamp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mVSyncEvent[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].vsync.count++;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mCondition.broadcast();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里将mVSyncEvent事件相关属性复制，且threadLoop等待阻塞唤醒，以便往下继续执行。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）EventThread的waitForEvent()，返回signalConnections，就是开始建立的Connection，这个Connection里面有个BitTube的写fd，另外的读fd在MessageQueue中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;此时我们回到上面没有讲的，当waitForEvent返回后，&lt;strong&gt;2. 把事件分发给listener；3. 然后调用每个连接的postEvent来发送Event。&lt;/strong&gt;这两个步骤。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;waitForEvent返回，调用conn-&amp;gt;postEvent(event)，我们查看Connection的postEvent函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; EventThread::Connection::postEvent(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; DisplayEventReceiver::Event&amp;amp; event) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;ssize_t&lt;/span&gt; size = DisplayEventReceiver::sendEvents(mChannel, &amp;amp;event, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; size &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ? &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt;(size) : &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt;(NO_ERROR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//位于frameworks/native/libs/gui/DisplayEventReceiver.cpp中&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;ssize_t&lt;/span&gt; DisplayEventReceiver::sendEvents(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;BitTube&amp;gt;&amp;amp; dataChannel,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Event &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* events, &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; count)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; BitTube::sendObjects(dataChannel, events, count);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;也就是通过Connection的写fd将event发送给MessageQueue。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这时候MessageQueue的looper epoll返回，最终会去调用response.request.callback-&amp;gt;handleEvent，最终调用的是mCallback(fd, events, data);而这个mCallback，既是MessageQueue::cb_eventReceiver。这一步可以查看&lt;a href=&quot;http://windrunnerlihuan.com/2016/07/31/Android%E6%B6%88%E6%81%AF%E6%9C%BA%E5%88%B6%E9%9B%B6%E6%95%A3%E5%88%86%E6%9E%90/&quot;&gt;Android消息处理零散分析&lt;/a&gt;的内容，如果忘记了，可以翻一翻。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以最终还是回到了MessageQueue::cb_eventReceiver：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; MessageQueue::cb_eventReceiver(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; fd, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; events, &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;* data) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    MessageQueue* &lt;span class=&quot;built_in&quot;&gt;queue&lt;/span&gt; = &lt;span class=&quot;keyword&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;MessageQueue *&amp;gt;(data);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;built_in&quot;&gt;queue&lt;/span&gt;-&amp;gt;eventReceiver(fd, events);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个步骤上面分析过了。最终去调用SF的onMessageReceived函数，最终每次Vsync信号来了，SF都会去执行handleMessageTransaction()等函数。&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::onMessageReceived(&lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; what) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ATRACE_CALL();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt; (what) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; MessageQueue::TRANSACTION:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        handleMessageTransaction();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; MessageQueue::INVALIDATE:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        handleMessageTransaction();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        handleMessageInvalidate();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        signalRefresh();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; MessageQueue::REFRESH:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        handleMessageRefresh();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这就是vsync信号的处理过程，和上面章节的结合在了一起。&lt;/p&gt;
&lt;h1 id=&quot;VSync实例&quot;&gt;&lt;a href=&quot;#VSync实例&quot; class=&quot;headerlink&quot; title=&quot;VSync实例&quot;&gt;&lt;/a&gt;VSync实例&lt;/h1&gt;&lt;h2 id=&quot;重要点小结&quot;&gt;&lt;a href=&quot;#重要点小结&quot; class=&quot;headerlink&quot; title=&quot;重要点小结&quot;&gt;&lt;/a&gt;重要点小结&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们列出了EventThread的重要function.下面一一说明其功能：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;EventThread::Connection::Connection()：&lt;/strong&gt;Connection的构造函数.用于进程间的通信by BitTube..在此处主要是搭建一个通路(BitTube)来完成client(App或SurfaceFlinger)对Vsync event事件的请求(通过requestNextVsync())和EventThread把SW-Vsync event callback到其感兴趣的client。需要注意的是App是通过SurfaceFlinger::createDisplayEventConnection()创建此连接的，而sufaceflinge是在其初始化时call EventQueue.setEventThread(mSFEventThread)创建的。所以对App 的EventThread 来说可能有多个connection ,也有可能没有，而对sufaceflinger目前来说有且只有一个；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;sp&lt;eventthread::connection&gt;EventThread::createEventConnection()：&lt;/eventthread::connection&gt;&lt;/strong&gt;创建 Connection连接；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;status_tEventThread::registerDisplayEventConnection()：&lt;/strong&gt;如其名所描述.其功能是把创建的Connection注册到一个容器中。当SW-VSYNCevent发生时，EventThread会从Connection注册的容器中，找到那些对SW-VSYNC event感兴趣的connection并把vsyncevent通过BitTube传到client；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;void EventThread::requestNextVsync()：&lt;/strong&gt;Clinet 端通过Connection call 这函数通知EventThread，其对SW-SYNCevent的请求；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;voidEventThread::onVSyncEvent(nsecs_t timestamp)：&lt;/strong&gt;SW-VSYNCEVENT 发生时，DispSyncSource 会call此函数，告知EventThread，Vsync event已经发生，如果此时有connect对Vsync感兴趣，EventThread便会通过connect-&amp;gt;postEvent(event)把Vsync事件发送到client端(App或surfaceflinger)；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;bool EventThread::threadLoop()：&lt;/strong&gt;线程的主体函数.其完成两件事，一是把对SW-VSYNC event有请求并且还没有处理的connect找出来，二是把Vsyncevent通过connect通知到client；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vector&amp;lt; sp&lt;eventthread::connection&gt;&amp;gt; EventThread::waitForEvent()：&lt;/eventthread::connection&gt;&lt;/strong&gt;EventThread 的主要功能都在此函数里，此函数由threadLoop()调用。EventThread在大部分时间里是sleep的，如果系统的性能比较好，那么其sleep的节奏是和SW-VSYNC event的节奏一致，即16.6mssleep一次。然而由于其App或surfaceflinger没有Vsync的请求，其sleep的时间为更长。此函数的名为waitForEvent，其到底在等什么event？原来此函数在等待的event就是Dispsync产生的SW-SYNC event，其功能check所有的connect是否有Vsync事件请求根据不同的情况做如下处理。&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;所有的connect都没有Vsync请求，则其通过disableVSyncLocked()，disableVsync event，那么此EventThread将不会收到SW-SYNCevent，一直sleep直到有connect有Vsync请求为止。&lt;/li&gt;
&lt;li&gt;在所有的connect中，有SW-SYNC event请求，但是当其请求SW-SYNCevent时，SW-SYNCevent还没有fire，则其通过enableVSyncLocked() enable Vsync并进入sleep。当下一个SW-SYNCevent来到时，便把所有有SW-SYNCevent请求的connection返回给threadLoop。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;下图是整个流程的大图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%94%29----VSync%20%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/big.jpg&quot; alt=&quot;big&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们接下来依然以gallery3d（相册）为例子，分析Vsync-app和Vsync-sf的工作流程。&lt;/p&gt;
&lt;h2 id=&quot;Vsync-app实例&quot;&gt;&lt;a href=&quot;#Vsync-app实例&quot; class=&quot;headerlink&quot; title=&quot;Vsync-app实例&quot;&gt;&lt;/a&gt;Vsync-app实例&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%94%29----VSync%20%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/app.png&quot; alt=&quot;app&quot;&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;App 通过Connection向EventThread请求SW-VSYNCevent(最终并且通过callEventThread::requestNextVsync()).一般来说App是通过Choreographer.doScheduleVsync()来请求Vsyncevent.&lt;/li&gt;
&lt;li&gt;DispSync 产生SW-VSYNC event并call DispSyncSource的onDispSyncEvent().&lt;/li&gt;
&lt;li&gt;DispSyncSource产生VSYNC-app信号跳变.&lt;/li&gt;
&lt;li&gt;同时DispSyncSource使EventThread(app)的waitForEvent()结束sleep,并把VSYNC-app通知到App进程(gallery3d).&lt;/li&gt;
&lt;li&gt;Gallery3d 进程收到VSYNC-app信号,在其main线程(UI Thread)中开始draw一个frame(发送draw command给GL thread).&lt;/li&gt;
&lt;li&gt;GL Thread 开始draw view.&lt;/li&gt;
&lt;li&gt;当GL thread 线程Draw 完一frame后,把draw buffer放到buffer queue中.&lt;/li&gt;
&lt;li&gt;SufaceView中画好的buffer 数据增加为1.这个buffer 将被surfaceflinger 在适当的时候合成.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;Vsync-sf实例&quot;&gt;&lt;a href=&quot;#Vsync-sf实例&quot; class=&quot;headerlink&quot; title=&quot;Vsync-sf实例&quot;&gt;&lt;/a&gt;Vsync-sf实例&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%94%29----VSync%20%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/sf.png&quot; alt=&quot;sf&quot;&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;App draw 完一个frame (SurfaceView) 并且把此frame通过调用BufferQueueProducer::queueBuffer()放到 bufferqueue中,并且通过call EventThread::requestNextVsync(),请求SW-VSYNCevent.此时由于DispSync没有fireSW-Sync event所以EventThread在EventThread::waitForEvent()中sleep.&lt;/li&gt;
&lt;li&gt;DispSync触发SW-SYNC event信号并且call DispSyncSource::onDispSyncEvent().&lt;/li&gt;
&lt;li&gt;在DispSyncSource::onDispSyncEvent()中首先引起Vsync-sf跳变,然后在call EventThread::onVSyncEvent(nsecs_ttimestamp).&lt;/li&gt;
&lt;li&gt;在EventThread::onVSyncEvent(nsecs_ttimestamp)中,会唤醒EventThread::waitForEvent()中的sleep,从而发送消息到Surfaceflinger.&lt;/li&gt;
&lt;li&gt;SurfaceFlinger收到EventThread发过来的Vsync-sf跳变信息,开始合成dirty layer, 本例是SurfaceView.合成完以后发送更新的消息到DisplayHW.&lt;/li&gt;
&lt;li&gt;Display HW 收到更新的消息时,HW vsync event还没有来,因此DisplayHW sleep了一段事件.当HWvsync event到来时,DisplayHW 便更新其LCD的内容.把最新的内容显示在LCD上.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;自此我们完成了Vsync子系统的分析。&lt;/p&gt;
&lt;h2 id=&quot;性能影响&quot;&gt;&lt;a href=&quot;#性能影响&quot; class=&quot;headerlink&quot; title=&quot;性能影响&quot;&gt;&lt;/a&gt;性能影响&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;回到系统性能上,我们可以看出系统的性能(FPS)可能于如下因素有关：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;DispSync的调度. DispSync是Vsync系统的心脏,如果DispSync来不及调度,则有可能由于去SW-SYNC event的产生不及时而影响系统的性能.&lt;/li&gt;
&lt;li&gt;View Draw 花费了过多的时间也会引性能问题, 如果其不能在一个SW-SYNC时间内完成, 那么此应用就会有一个Janks.由于现在的Androd系统都采用了HWUI,viewdraw往往是GPU直接draw,所以很多时候是GPUperformance问题.&lt;/li&gt;
&lt;li&gt;HW display 的性能问题.LCD 上所绘画的内容, 最终需要HW display在HW vsync触发是把其内容显示在LCD上.&lt;/li&gt;
&lt;li&gt;Binder 的调度问题, 我们可以看到无论是requestNextVsync () 还是queueBuffer()都是App通过binder与surfaceflinger进程通信的.而这些binder在大多数时间是sleep的.如果binder由于CPU调度而错过了一个Vsync跳变点,那么就有一个frame发生Janks.&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&quot;结语&quot;&gt;&lt;a href=&quot;#结语&quot; class=&quot;headerlink&quot; title=&quot;结语&quot;&gt;&lt;/a&gt;结语&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;对于VSync信号的学习就到这里，我们可以看到还是十分复杂的。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%94%29----VSync%20%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/meizi.jpg&quot; alt=&quot;meizi&quot;&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;VSync信号的科普我们上一篇已经介绍过了，这篇我们要分析在SurfaceFlinger中的作用。（愈发觉得做笔记对自己记忆模块巩固有很多帮助，整理文章不一定是用来给别人看的，但一定是为加强自己记忆的~）&lt;br&gt;
    
    </summary>
    
      <category term="Android技术点" scheme="http://windrunnerlihuan.com/categories/Android%E6%8A%80%E6%9C%AF%E7%82%B9/"/>
    
    
      <category term="SurfaceFlinger" scheme="http://windrunnerlihuan.com/tags/SurfaceFlinger/"/>
    
  </entry>
  
  <entry>
    <title>VSync信号</title>
    <link href="http://windrunnerlihuan.com/2017/05/21/VSync%E4%BF%A1%E5%8F%B7/"/>
    <id>http://windrunnerlihuan.com/2017/05/21/VSync信号/</id>
    <published>2017-05-21T05:02:22.000Z</published>
    <updated>2019-01-06T07:32:06.502Z</updated>
    
    <content type="html">&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在我们详细分析SurfaceFlinger之前要了解一下VSync信号，为下一节分析Vsync工作原理打下基础。&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;VSync信号相关&quot;&gt;&lt;a href=&quot;#VSync信号相关&quot; class=&quot;headerlink&quot; title=&quot;VSync信号相关&quot;&gt;&lt;/a&gt;VSync信号相关&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;首先我们要了解以下几个概念：&lt;/p&gt;
&lt;h2 id=&quot;屏幕刷新率&quot;&gt;&lt;a href=&quot;#屏幕刷新率&quot; class=&quot;headerlink&quot; title=&quot;屏幕刷新率&quot;&gt;&lt;/a&gt;屏幕刷新率&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;即 Refresh Rate 或 Scanning Frequency，单位赫兹/Hz，是指设备刷新屏幕的频率，该值对于特定的设备来说是个常量，如 60hz。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;每一台CRT显示器都有自己的刷新率，其单位是Hz，其数值是显示器每秒钟更新画面的次数。不同的显示器支持再不同分辨率下的不同刷新率。它的范围可以从低到60高到100。&lt;strong&gt;注意它不是你游戏中所提到的那个FPS&lt;/strong&gt;。如果你设置了一个特定的刷新率，显示器将一直按照这个速率刷新画面。甚至画面没有任何的改变。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;液晶显示器就不同了。LCD的每个像素在被告知改变的时候将一直是亮着的。他们不需要刷新。但是因为VGA(或是DVI)的工作原理，LCD不得不从显示卡那里按一定的速率得到新的新画面。这就是虽然LCD不必要更新，但是他还是有自己的刷新率。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如下图，屏幕的刷新过程是每一行从左到右（行刷新，水平刷新，Horizontal Scanning），从上到下（屏幕刷新，垂直刷新，Vertical Scanning）。当整个屏幕刷新完毕，即一个垂直刷新周期完成，会有短暂的空白期，此时发出 VSync 信号。所以，VSync 中的 V 指的是垂直刷新中的垂直/Vertical。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;(显示器的扫描方式分为“&lt;strong&gt;逐行扫描&lt;/strong&gt;”和“&lt;strong&gt;隔行扫描&lt;/strong&gt;”两种。逐行扫描比隔行扫描拥有列稳定显示效果。早期的显示器因为成本所限，使用逐行扫描方式的产品要比隔行扫描的贵许多，但随着技术进步，隔行扫描显示器现在已经被淘汰。我们可以翻一翻《&lt;code&gt;电视原理&lt;/code&gt;》)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/VSync%E4%BF%A1%E5%8F%B7/shuaxin.png&quot; alt=&quot;屏幕刷新过程&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;对于一个特定的设备，帧率和刷新频率没有必然的大小关系。&lt;/p&gt;
&lt;h2 id=&quot;帧率&quot;&gt;&lt;a href=&quot;#帧率&quot; class=&quot;headerlink&quot; title=&quot;帧率&quot;&gt;&lt;/a&gt;帧率&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;即 Frame Rate，单位 fps，是指 gpu 生成帧的速率，如 33 fps，60fps，越高越好。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我想这里的每一人都明白FPS。它显示显示卡在每秒钟可以描画多少画面。这显然是越高越好。&lt;strong&gt;但是对于快速变化的游戏而言，你的FPS很难一直保持同样的数值，他会随着你所看到的显示卡所要描画的画面的复杂程度而变化&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id=&quot;VSync&quot;&gt;&lt;a href=&quot;#VSync&quot; class=&quot;headerlink&quot; title=&quot;VSync&quot;&gt;&lt;/a&gt;VSync&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;安卓系统中有 2 种 VSync 信号：屏幕产生的硬件 VSync 和由 SurfaceFlinger 将其转成的软件 Vsync 信号。后者经由 Binder 传递给 Choreographer。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;硬件 VSync 是一个脉冲信号，起到开关或触发某种操作的作用。 &lt;/p&gt;
&lt;h3 id=&quot;显示器参数&quot;&gt;&lt;a href=&quot;#显示器参数&quot; class=&quot;headerlink&quot; title=&quot;显示器参数&quot;&gt;&lt;/a&gt;显示器参数&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;TFT LCD 有 vsync,hsync,hspw,hbpd,hfpd, vspw,vbpd, vfpd 等参数，这些参数都是由以前的 CRT(阴极射线显像管)带过来的, 而 TFT 液晶跟 CRT 显示方法根本不同, 至于为什么这些参数也会引入到 TFT 中,大概是因为VGA(或是DVI)工作原理，上文提到过&lt;/strong&gt;。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这网站有更权威的描述 &lt;a href=&quot;http://www.linux-fbdev.org/HOWTO/2.html&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;http://www.linux-fbdev.org/HOWTO/2.html&lt;/a&gt; ，然后是英文。。。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;CRT 侧面看是个漏斗状的真空的东东, 根部就是电子枪, 打出的电子撞击前面的玻璃面上的荧光物质, 荧光物发光. 控制电子枪按规律射出电子, 逐行的打到荧光物质上, 打完一行(也即扫描完一行), 就回头扫描下一行….. 扫描完一个显示屏所有的行后, 就是一幅完整的画面了, 称为一帧(frame), 扫描过程如果非常快, 人眼看到是一幅完整画面, 但实际是一个个点发不同光组成的. 扫描得慢时, 就会觉得闪烁了(以前听老师讲课, 说在他们的年代, 能明显看到一行一行刷过的壮观场景)。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;一帧扫描完, 再回头从第一行开始继续扫描, 重复过程. 看到的就是持续在显示的画面了(实际上, 电子的运动轨迹是由磁场控制的, 电子枪没有机械的运动, 为好理解, 就当是电子枪做了机械运动吧)。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;描述方式多数显示器选择从左上角开始, 从左至右, 到了右边界, 再偏转到左边界的下一行, 这是所谓的”Z”型扫描。类似地扫描完最后一帧时, 要偏转回左上角起始处, 准备扫描下一帧。这个上面那一幅图描述过了。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;code&gt;(科普一下，ignore it。start------)&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HSYNC 信号用于告诉电子枪该扫描下一行了, 即要转到下一行起始处了；&lt;/li&gt;
&lt;li&gt;VSYNC 信号告诉电子枪该显示下一帧了, 即该转回左上角起始处了；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;H for Horizontal, V for vertical。在这里 Hsync, Vsync 两者各表示一种信号, 分别由 HSPW 及 VSPW 两个参数确定信号持续时间, 也就是脉冲的宽度.&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在扫描一行中, 首先&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;HSYNC 脉冲信号为高电平, 一发出此信号, 电子枪迅速移回左边界, 期间电子枪不发射电子.&lt;/li&gt;
&lt;li&gt;在 HSYNC 信号持续时间上的某点, 电子枪开始再次向右扫描了, 等 HSYNC 信号结束, 表示该开始显示下一行的数据了, 电子枪又要开始发射电子. &lt;/li&gt;
&lt;li&gt;在HSYNC 信号结束与开始显示数据之间, 可以插入一段延时(由 HBPD 参数控制)让显示屏仍然不显示有效数据(效果就是黑色), 是为显示屏左边框. &lt;/li&gt;
&lt;li&gt;到 HFPD 结束, 电子枪才可以发射电子, 显示该行的有效数据.&lt;/li&gt;
&lt;li&gt;显示完毕. 又该开始发出 HSYNC 信号了. 在一行中有效数据扫描完毕与 HSYNC 信号发出之间也插入一段延时 HFPD, 是为显示屏右边框,之后, 就是重复过程了.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;因此, 显示一行时序为： HSPW -&amp;gt; HBPD -&amp;gt; 扫描数据 -&amp;gt; HFPD .&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;类似地, 垂直扫描一帧的时序：VSPW -&amp;gt; VBPD -&amp;gt; 扫描有效行 -&amp;gt; VFPD .&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;为什么要有边框(vbpd, vfpd, hbpd, hfpd)? 按上边贴出网页的说法:&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Usually, one doesn’t use that feature nowadays, as we have tunable monitors that allow stretching the mode to the physical limits of the monitor.&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我的理解是:确实是以前的显示器调整显示屏边界用的,而新的显示有调整能力了, 所以不再需要刻意关注了,但术语被保留了下来.&lt;/p&gt;
&lt;h3 id=&quot;举个栗子&quot;&gt;&lt;a href=&quot;#举个栗子&quot; class=&quot;headerlink&quot; title=&quot;举个栗子&quot;&gt;&lt;/a&gt;举个栗子&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;对于 TFT LCD, 但这些参数作用是同样的. 但如何确定 ?  TFT 的 LCD 的 datasheet 中一定得标有。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如型号 WXCAT35-TG3  3.5 寸的液晶中有表如下:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/VSync%E4%BF%A1%E5%8F%B7/sheet.png&quot; alt=&quot;LCD参数表&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;对照下边的时序图(注: &lt;font color=&quot;#FF0000&quot;&gt;时序图的 Vsync, Hsync 信号(红框圈出的)跟上边讲的有点出入, 信号都是低电平, 而非高电平, 因此编程时要设置信号反相&lt;/font&gt;, 如s3c244a 的 LCDCON5的INVLINE 及 INVFRAME 即是干这活的):&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/VSync%E4%BF%A1%E5%8F%B7/sheetpng.png&quot; alt=&quot;同步信号时序&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;tvp 即 VSPW&lt;/li&gt;
&lt;li&gt;tvb 即 VBPD&lt;/li&gt;
&lt;li&gt;tvf 即 VFPD&lt;/li&gt;
&lt;li&gt;thp 即 HSPW&lt;/li&gt;
&lt;li&gt;thb 即 HBPD&lt;/li&gt;
&lt;li&gt;thf 即 HFPD&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;参考的时钟就是 CLK, 一个 CLK 时钟, 完成一个像素点的显示。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;计算帧频率(刷新频率)的方法就是所有的像素点跟边沿(边框,hbpd 之类),同步脉冲的时间相加, 结果就是显示完整一帧所需时间, 其倒数即是帧频率。&lt;/p&gt;
&lt;h3 id=&quot;Linux-的-LCD-驱动&quot;&gt;&lt;a href=&quot;#Linux-的-LCD-驱动&quot; class=&quot;headerlink&quot; title=&quot;Linux 的 LCD 驱动&quot;&gt;&lt;/a&gt;Linux 的 LCD 驱动&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;LCD 驱动主要得完成两部分, 一是跟 framebuffer 注册驱动； 二是设置 LCD 控制器的寄存器, 以适配 LCD。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;struct fb_info  是关键, 有显示驱动的所有信息, 要拿此结构跟 framebuffer 注册, 代表着本驱动,  该结构定义在 ,在驱动程序中, 主体部分就是实现 struct fb_info .&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在&lt;a href=&quot;http://windrunnerlihuan.com/2017/03/12/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B8%80-Android%E5%9B%BE%E5%BD%A2%E6%98%BE%E7%A4%BA%E4%B9%8BHAL%E5%B1%82Gralloc%E6%A8%A1%E5%9D%97%E5%AE%9E%E7%8E%B0/&quot;&gt;Android SurfaceFlinger 学习之路(一)—-Android图形显示之HAL层Gralloc模块实现&lt;/a&gt;中提到过这一部分。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在该结构中, 以下定义的三个字段也是比较重要的, 要填一些数据入去:&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; fb_var_screeninfo var;   &lt;span class=&quot;comment&quot;&gt;/* Current var */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; fb_fix_screeninfo fix;   &lt;span class=&quot;comment&quot;&gt;/* Current fix */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; fb_ops *fbops;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;struct fb_fix_screeninfo 里定义的 pixclock 是像素点的周期, 单位是皮秒, 数值等于像素点显示频率的倒数. 如上图贴出的表格中, Dclk 那行中, 6.4 Mhz 就是频率, 频率倒数即为周期, 换算出来为 156250 ps, 约为表中给出的 156 ns.&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;驱动具体的实现, 要看开发板对应的驱动源码文件, 一般位于 kernel_src/drivers/video/ 下,我们以前下的Android源码，找到对应设备分支下的，应为位于kernel/{branch}/drivers/video/吧。&lt;/p&gt;
&lt;h3 id=&quot;简单描述&quot;&gt;&lt;a href=&quot;#简单描述&quot; class=&quot;headerlink&quot; title=&quot;简单描述&quot;&gt;&lt;/a&gt;简单描述&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在手机平台，LCD,Camera，TV的接线上，都会用到PCLK，VSYNC和HSYNC这三个信号。可见这三个信号和显示关系非常大。首先我们先看这三个信号的作用：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PCLK：有些方案给他起名字叫：DotCLK。是像素点同步时钟信号。也就是每个PCLK对应一个像素点。&lt;/li&gt;
&lt;li&gt;VSYNC：是场同步信号。以高电平有效为例，VSYNC置高直到被拉低，这个区段所输出的所有影像数据组成一个frame。&lt;/li&gt;
&lt;li&gt;HSYNC：是行同步信号。就是在告诉接收端：“HSYNC”有效时段内接收端接收到的所有的信号输出属同一行。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;若要显示一个640x480的画面，显示不正确的时候，若量PCLK，VSYNC和HSYNC这三个信号，就可以知道这三个信号配置是否有问题，一般来讲，这种情况是有公式的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;VSync = HSYNC x 320；&lt;/li&gt;
&lt;li&gt;Hsync = PCLK x 640；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;sensor的同步信号可以简单的理解为sensor向其信号接收端所发送的宣告信号。比如HSYNC，就是sensor这告诉接收端：“HSYNC”有效时段内sensor所有的信号输出属同一行。VSYNC同理，以高电平有效为例，VSYNC置高直到被拉低，这个区段sensor所输出的所有影像数据组成一个frame。同步信号的频率决定于pixel clock，比如一行有640个pixel，那么HSYNC的频率为：PCLK/(640+dummy);Vsync同理。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;code&gt;(科普结束，ignore it，too。end------)&lt;/code&gt;&lt;/p&gt;
&lt;h1 id=&quot;VSync-信号的作用&quot;&gt;&lt;a href=&quot;#VSync-信号的作用&quot; class=&quot;headerlink&quot; title=&quot;VSync 信号的作用&quot;&gt;&lt;/a&gt;VSync 信号的作用&lt;/h1&gt;&lt;h2 id=&quot;tearing-画面撕裂&quot;&gt;&lt;a href=&quot;#tearing-画面撕裂&quot; class=&quot;headerlink&quot; title=&quot;tearing 画面撕裂&quot;&gt;&lt;/a&gt;tearing 画面撕裂&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;首先，我们来看下，没有引入 VSync 时，屏幕显示图像的工作流程。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/VSync%E4%BF%A1%E5%8F%B7/single.png&quot; alt=&quot;单缓冲&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如上图，CPU/GPU 向 Buffer 中生成图像，屏幕从 Buffer 中取图像、刷新后显示。这是一个典型的生产者——消费者模型。理想的情况是帧率和刷新频率相等，每绘制一帧，屏幕显示一帧。而实际情况是，二者之间没有必然的大小关系，如果没有锁来控制同步，很容易出现问题。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所谓”撕裂”就是一种画面分离的现象，就象你照一张照片，在旋转哪怕一度再照一张照片，然后把两张照片的从中间裁开，用一张照片的上半部与另一张的下半部对接起来。这样得到的画像虽然相似但是上半部和下半部确实明显的不同。这就被称之为视觉现实上的撕裂。它不会一直从中间分开，它可能靠近上面也可能下面，分离点可能在屏幕上下移动，也可能在两点间前后移动。（&lt;strong&gt;译者：原文的作者实在是啰嗦，其实就是画面移动较快的时候，画面看上去是两截&lt;/strong&gt;。这种现象恐怕打游戏的都看到过，最好玩过PS2游戏的，用模拟器，在比较差的显卡和CPU上面，撕裂现象更为明显）。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/VSync%E4%BF%A1%E5%8F%B7/tearing.png&quot; alt=&quot;画面撕裂&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;为什么会发生这种现象呢？让我们举一个特定的例子。让我们假定你的显示器的刷新率是75Hz, 你真在玩你最喜欢的游戏，而且你现在有100的FPS.这就意味着你的显示器每秒更新75次画面，而你的显示卡每秒更新100次，比你的显示器快33%。这就意味着在你的显示器更新画面的时间里，显示卡描画了1+1/3的画面。这样在画面显示的时候，那个1/3的画面就会覆盖那个完整画面上部的1/3。在下次的图像刷新的时候，显示卡会描画剩下来得2/3和新的2/3的画面。这样，因为屏幕的更新只能跟上画面更新的2/3，这样图像的上部的1/3或是下部的1/3就会和剩下的画面合不上。如果画面的变化不大可能不太会注意到这一点，但是如果你快速的环顾四周那就会非常的明显。&lt;/p&gt;
&lt;h2 id=&quot;Double-Buffer-双缓冲&quot;&gt;&lt;a href=&quot;#Double-Buffer-双缓冲&quot; class=&quot;headerlink&quot; title=&quot;Double Buffer 双缓冲&quot;&gt;&lt;/a&gt;Double Buffer 双缓冲&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;现在，一个很普遍的误解就产生了。一些人认为解决这个问题的方法就是简单设置一个FPS的限制让FPS不超过显示器的刷新率，这样显示卡就不会超过75FPS,这样就可以了。真的吗？错！&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在我解释为什么之前，让我来讲一下双倍缓冲。双倍缓冲一种用来减轻撕裂问题，虽然不是很完全。基本上来说你有一个显示缓冲和一个后备缓冲。当显示器要显示画面的时候，就会从显示缓冲里“推出”显示画面。显示卡则在后备缓冲里描画另外一个新画面，当描画完成后则将新画面考入显示缓冲里。但是这个过程需要时间，如果显示器的刷新在拷贝过程中进行的话，显示器上显示的仍然是个”撕裂”的画面。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;VSync 通过建立一个不让在显示器刷新前将后备缓冲中的画面拷贝到显示缓冲中的规定来解决这个问题。如果FPS高于刷新率的话，没有问题。后备缓冲的更新完成后，系统处于等待状态。当显示器刷新后，后备缓存考入显示缓存，显示卡则可以在后备缓存里描画新的画面，这样就很有效的将你的FPS限制在显示器的刷新率的范围内。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;为了解决单缓存的“tearing”问题，双缓存和 VSync 应运而生。双重缓存模型如下图： &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/VSync%E4%BF%A1%E5%8F%B7/double.png&quot; alt=&quot;双缓冲&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;两个缓存区分别为 Back Buffer 和 Frame Buffer。GPU 向 Back Buffer 中写数据，屏幕从 Frame Buffer 中读数据。VSync 信号负责调度从 Back Buffer 到 Frame Buffer 的复制操作，可认为该复制操作在瞬间完成。其实，该复制操作是等价后的效果，实际上双缓冲的实现方式是&lt;strong&gt;交换&lt;/strong&gt; Back Buffer 和 Frame Buffer 的名字，更具体的说是交换内存地址（有没有联想到那道经典的笔试题目：“有两个整型数，如何用最优的方法交换二者的值？”），通过二进制运算“异或”即可完成，所以可认为是瞬间完成。(《数字电路技术》当中有一章节应该讲过运算器还是控制器来着，可以设计一个异或电路。忘了，回去翻一翻~)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;附加小福利：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;假设两个数x和y，则有：&lt;br&gt;方法1，算术运算（加减）：&lt;br&gt;x=x+y;  //x暂存两数之和&lt;br&gt;y=x-y;  //y为两数之和减去y，即原来的x&lt;br&gt;x=x-y;  //x为两数之和减去现在的y（原来的x），变成原来的y&lt;br&gt;方法2，逻辑运算（异或）：&lt;br&gt;x^=y; //x先存x和y两者的信息&lt;br&gt;y^=x; //保持x不变，利用x异或反转y的原始值使其等于x的原始值&lt;br&gt;x^=y; //保持y不变，利用x异或反转y的原始值使其等于y的原始值&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;双缓冲的模型下，工作流程这样的：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在某个时间点，一个屏幕刷新周期完成，进入短暂的刷新空白期。此时，VSync 信号产生，先完成复制操作，然后通知 CPU/GPU 绘制下一帧图像。复制操作完成后屏幕开始下一个刷新周期，即将刚复制到 Frame Buffer 的数据显示到屏幕上。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在这种模型下，只有当 VSync 信号产生时，CPU/GPU 才会开始绘制。这样，当帧率大于刷新频率时，帧率就会被迫跟刷新频率保持同步，从而避免“tearing”现象。&lt;/p&gt;
&lt;h2 id=&quot;Jank-掉帧&quot;&gt;&lt;a href=&quot;#Jank-掉帧&quot; class=&quot;headerlink&quot; title=&quot;Jank 掉帧&quot;&gt;&lt;/a&gt;Jank 掉帧&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;注意，当 VSync 信号发出时，如果 GPU/CPU 正在生产帧数据，此时不会发生复制操作。屏幕进入下一个刷新周期时，从 Frame Buffer 中取出的是“老”数据，而非正在产生的帧数据，即两个刷新周期显示的是同一帧数据。这是我们称发生了“掉帧”（Dropped Frame，Skipped Frame，Jank）现象。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;让我们来看一个另外一个不同的例子。让我们假定你已经玩到了你最喜欢的游戏的最后一关，这个游戏有很好的图像.你显示器的刷新率还是在75。但是你的FPS现在只有50了，比刷新率要低33%.这就意味着每次显示器刷新图像，你的显示卡只能画出下一桢画面的2/3。让我们看看它是如何工作的。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;显示器刚刚更新，第一桢的画面已经拷贝到显示缓冲，第二桢的画面的2/3被写入后备缓冲。&lt;/li&gt;
&lt;li&gt;这时显示器重新刷新，它会第一次从显示缓冲里提取第一桢的画面。然后显示卡开始完成的第二桢剩下的部分。但是它必须等待，应为再下一次刷新之前它是不会上传的。&lt;/li&gt;
&lt;li&gt;显示器再次刷新，显示器不得不第二次从显示缓冲里提取第一桢的画面，然后第二桢的画面被写入显示缓冲。显示卡在后备缓冲中写入第三桢的2/3。&lt;/li&gt;
&lt;li&gt;等到显示器刷新，第一次从显示缓冲里提取第二桢的画面，显示卡开始完成的第三桢剩下的部分。然后又是第二次从显示缓冲里提取第二桢的画面，然后第三桢的画面被写入显示缓冲。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如此类推。这样4次显示器刷新，我们只能的到2桢的画面。如果刷新率是75的话，我们只能得到35的FPS.很明显这个数值要低于显示卡可以带到的50FPS.这主要就是应为显示卡不得不在描画后备缓冲上浪费时间。而在此过程中，后备缓冲上的画面是不能被拷贝到显示缓冲。理论上讲，双缓冲的VSync,FPS将是一组不连续的整数，其等于刷新率/n,n是正整数。也就是说，如果你的刷新率是60hz,你能得到的FPS只能是 60，30，20，15，12，10 等等。你可以注意到60到30是一个相当大的差距。只要的显示卡的FPS在60到30之间，你说得到的真实FPS都将只能等于30！&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如下图，A、B 和 C 都是 Buffer。蓝色代表 CPU 生成 Display List，绿色代表 GPU 执行 Display List 中的命令从而生成帧，黄色代表生成帧完成。 &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/VSync%E4%BF%A1%E5%8F%B7/jank.png&quot; alt=&quot;Jank&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;现在，你明白为什么有人不喜欢它了。让我们回到一开始的那个例子。你在玩你最喜欢的游戏，刷新率是75HZ,100FPS。你打开VSync.游戏就被限制在75FPS,没有问题，没有撕裂图像，看起来不错。你到了一个图像特别复杂的地方，在不用VSync的时候，你的FPS下降到了60左右。但是你打开了VSync，你的FPS实际就只有37.5。这样你的游戏突然从75FPS变成了37.5FPS,不管37.5仍然很流畅但是你一定会注意到刷新率突然减少了一半。当让如果以下变到25FPS的话，实际的现实率可能就只有17.5。本来还可以玩的游戏，就变成了幻灯片。这就是大家不喜欢它的原因。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果你的游戏的FPS可以一直稳定的大于显示器的刷新率，VSync是个不错的东西。但是如果FPS忽大忽小。VSync就是让人烦的东西。如果你的游戏FPS一直都小于刷新率的话，实际的FPS要远远小于显示卡可以显示的FPS.看上去就象是VSync降低了你的FPS,但是从技术角度讲，不是应为图像太复杂，而是因为VSync就是这样工作的。&lt;/p&gt;
&lt;h2 id=&quot;Triple-Buffer-三缓冲&quot;&gt;&lt;a href=&quot;#Triple-Buffer-三缓冲&quot; class=&quot;headerlink&quot; title=&quot;Triple Buffer 三缓冲&quot;&gt;&lt;/a&gt;Triple Buffer 三缓冲&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;双重缓存的缺陷在于：当 CPU/GPU 绘制一帧的时间超过 16 ms 时，会产生 Jank。更要命的是，产生 Jank 的那一帧的显示期间，GPU/CPU 都是在闲置的。 &lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;也不是说所有的希望都没有了。现在的triple-buffering技术可以用来解决这个问题。让我们再来看刷新率75。FPS50的例子。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;第一桢在显示缓冲，第二桢的2/3在后备缓冲。&lt;/li&gt;
&lt;li&gt;显示器刷新第一桢第一次被显示，在后备缓冲里描画第二桢的剩下的1/3，在第二后备缓冲里描画第三桢的1/3(因为我们有三级缓冲了)。&lt;/li&gt;
&lt;li&gt;显示器再次刷新第一桢第二次被显示，第二桢放入在显示缓冲，第三桢的的1/3放入后备缓冲，第二后备缓冲里描画第三桢剩下的2/3。&lt;/li&gt;
&lt;li&gt;接下来显示器再次刷新的时候，第二桢被显示，第三桢就可以放入显示缓冲，这样我们就可以在3次刷新中得到2桢的画面。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;也就是刷新率的2/3,也就是50FPS.triple-buffering理论上讲可以避免缓冲写入是带来的延迟现象，这样就不会浪费时间。但是triple-buffering并不是适用于所有的游戏。实际上它并不是普及(这个文章可能写的太早，现在triple-buffering已经很普及了)，而且它也会影响显示卡的性能，应为它需要更多的显示内存，需要更多时间在内存之间降数据拷贝来拷贝去。但是triple-buffering确实是一个很好的方法，既可以消除撕裂画面又可以不像普通VSync一样影响你的FPS.&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果有第三个 Buffer 能让 CPU/GPU 在这个时候继续工作，那就完全可以避免第二个 Jank 的发生了！&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/VSync%E4%BF%A1%E5%8F%B7/triple.png&quot; alt=&quot;三缓冲&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;于是就有了三缓存：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/VSync%E4%BF%A1%E5%8F%B7/swap.png&quot; alt=&quot;三缓冲交换&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;工作原理同双缓冲类似，只是多了一个 Back Buffer。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;需要注意的是，第三个缓存并不是总是存在的，只要当需要的时候才会创建。之所以这样，是因为三缓存会显著增加用户输入到显示的延迟时间。如上图，帧 C 是在第 2 个刷新周期产生的，但却是在第 4 个周期显示的。最坏的情况下，你会同时遇到输入延迟和卡顿现象。&lt;/p&gt;
&lt;h2 id=&quot;三缓冲局限&quot;&gt;&lt;a href=&quot;#三缓冲局限&quot; class=&quot;headerlink&quot; title=&quot;三缓冲局限&quot;&gt;&lt;/a&gt;三缓冲局限&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我希望这篇文章是有用的，可以帮出你理解VSync的工作原理。（特别是不再犹豫是否打开VSync）总之，如果没有triple-buffering的情况下，如何权衡Vsync的FPS限制和消除撕裂画面带来的视觉感受，那将完全取决于你个人的喜好。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;译者按：如果这篇文章的机理是正确的。triple-buffering也不是万能的，实际上就是把减少1/2变成了减少1/3而已，如果是FPS恰好卡到了一定的数值的时候没有问题，一旦没有，那就绝对要损失FPS.所以对于那种FPS刚刚超过24的游戏，不管有没有triple-buffering，都应该关.&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以一定会有人问：液晶显示器的刷新频率为何不能调高？&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里有一个误解。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;原来我们使用的是CRT技术的显示器,为保证长时间地注视屏幕而眼睛不疲劳,我们一般都会把刷新率调到75H甚至是85Hz,这是由于CRT技术的特性决定的,刷新率越高也就意味着图像越清楚、越稳定。但是对于LCD来说,由于液晶板本身并不发光,只是液晶分子控制光线的偏转或通过,发光的是背光源,即荧光灯管,在使用的时候即使把刷新率调到60Hz你也不会感到屏幕在闪烁,“刷新率”对LCD来说已经没有多大意义了,所以在使用液晶显示器的时候,我们是不必过于苛求刷新率的高低的。&lt;/p&gt;
&lt;h1 id=&quot;参考&quot;&gt;&lt;a href=&quot;#参考&quot; class=&quot;headerlink&quot; title=&quot;参考&quot;&gt;&lt;/a&gt;参考&lt;/h1&gt;&lt;p&gt;Getting To Know Android 4.1, Part 3: Project Butter - How It Works And What It Added&lt;br&gt;&lt;a href=&quot;http://www.androidpolice.com/2012/07/12/getting-to-know-android-4-1-part-3-project-butter-how-it-works-and-what-it-added/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;http://www.androidpolice.com/2012/07/12/getting-to-know-android-4-1-part-3-project-butter-how-it-works-and-what-it-added/&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;总结&quot;&gt;&lt;a href=&quot;#总结&quot; class=&quot;headerlink&quot; title=&quot;总结&quot;&gt;&lt;/a&gt;总结&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;本篇科普一下VSync，下一节开始分析它在SurfaceFlinger中的工作流程。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/VSync%E4%BF%A1%E5%8F%B7/meizi.jpg&quot; alt=&quot;妹子&quot;&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在我们详细分析SurfaceFlinger之前要了解一下VSync信号，为下一节分析Vsync工作原理打下基础。&lt;br&gt;
    
    </summary>
    
      <category term="科普分享" scheme="http://windrunnerlihuan.com/categories/%E7%A7%91%E6%99%AE%E5%88%86%E4%BA%AB/"/>
    
    
      <category term="VSync" scheme="http://windrunnerlihuan.com/tags/VSync/"/>
    
  </entry>
  
  <entry>
    <title>Android SurfaceFlinger 学习之路(四)----SurfaceFlinger服务的启动与连接过程</title>
    <link href="http://windrunnerlihuan.com/2017/05/13/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%9B%9B-SurfaceFlinger%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%90%AF%E5%8A%A8%E4%B8%8E%E8%BF%9E%E6%8E%A5%E8%BF%87%E7%A8%8B/"/>
    <id>http://windrunnerlihuan.com/2017/05/13/Android-SurfaceFlinger-学习之路-四-SurfaceFlinger服务的启动与连接过程/</id>
    <published>2017-05-13T06:45:23.000Z</published>
    <updated>2019-01-06T07:30:11.749Z</updated>
    
    <content type="html">&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上一篇我们分析了Android的开机动画启动流程，这一篇我们基于上一篇的基础，分析一下SurfaceFlinger的启动，还有连接它的过程。&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;SurfaceFlinger的启动&quot;&gt;&lt;a href=&quot;#SurfaceFlinger的启动&quot; class=&quot;headerlink&quot; title=&quot;SurfaceFlinger的启动&quot;&gt;&lt;/a&gt;SurfaceFlinger的启动&lt;/h1&gt;&lt;h2 id=&quot;启动概述&quot;&gt;&lt;a href=&quot;#启动概述&quot; class=&quot;headerlink&quot; title=&quot;启动概述&quot;&gt;&lt;/a&gt;启动概述&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceFlinger服务是一个独立进程，并且负责统一管理设备的帧缓冲区。通过上一篇开机动画流程分析，我们可以在init.rc中找到SurfaceFlinger服务配置的地方，位于system/core/rootdir/Init.rc中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;service surfaceflinger /system/bin/surfaceflinger&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; core&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    user system&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    group graphics drmrpc&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    onrestart restart zygote&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在硬件设备/system/bin/下，可以找到SurfaceFlinger的应用程序。我们查看源码frameworks/native/services/surfaceflinger/Android.mk文件：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;###############################################################&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;# build surfaceflinger&#39;s executable&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;include $(CLEAR_VARS)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;LOCAL_CFLAGS:= -DLOG_TAG=\&quot;SurfaceFlinger\&quot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;# SurfaceFlinger启动文件&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;LOCAL_SRC_FILES:= \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    main_surfaceflinger.cpp &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;LOCAL_SHARED_LIBRARIES := \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    libsurfaceflinger \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    libcutils \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    liblog \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    libbinder \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    libutils&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;# SurfaceFlinger是个动态库&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;LOCAL_MODULE:= surfaceflinger&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;ifdef TARGET_32_BIT_SURFACEFLINGER&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;LOCAL_32_BIT_ONLY := true&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;endif&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;include $(BUILD_EXECUTABLE)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从Makefile文件可以看出，相关依赖和主文件会被编译成libsurfaceflinger.so，然后SurfaceFlinger是对库的一个“封装调用”，里面有个main_surfaceflinger.cpp，我们可以沿着它的main函数往下分析。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;启动流程大概如下图，我才刚刚学了时序图，不知道画的对不对。。。。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%9B%9B%29----SurfaceFlinger%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%90%AF%E5%8A%A8%E4%B8%8E%E8%BF%9E%E6%8E%A5%E8%BF%87%E7%A8%8B/init.jpg&quot; alt=&quot;SurfaceFlinger服务的启动过程&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;启动过程&quot;&gt;&lt;a href=&quot;#启动过程&quot; class=&quot;headerlink&quot; title=&quot;启动过程&quot;&gt;&lt;/a&gt;启动过程&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceFlinger的main函数在framework/native/services/surfaceflinger/main_surfaceflinger.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt;**)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// When SF is launched in its own process, limit the number of&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// binder threads to 4.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//在该进程设置了binder线程池最大数为4&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ProcessState::self()-&amp;gt;setThreadPoolMaxThreadCount(&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// start the thread pool&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//这里其实只是将当前线程加入到这个Binder线程池中去&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;ProcessState&amp;gt; ps(ProcessState::self());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ps-&amp;gt;startThreadPool();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// instantiate surfaceflinger&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//创建一个SurfaceFlinger强引用对象&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;SurfaceFlinger&amp;gt; flinger = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; SurfaceFlinger();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; defined(HAVE_PTHREADS)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    setpriority(PRIO_PROCESS, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, PRIORITY_URGENT_DISPLAY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    set_sched_policy(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, SP_FOREGROUND);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// initialize before clients can connect&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//调用SurfaceFlinger的init函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    flinger-&amp;gt;init();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// publish surface flinger&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//把SurfaceFlinger服务注册到ServiceManager中&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;IServiceManager&amp;gt; sm(defaultServiceManager());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sm-&amp;gt;addService(String16(SurfaceFlinger::getServiceName()), flinger, &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// run in this thread&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//运行这个UI渲染流程&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    flinger-&amp;gt;run();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;main函数包含以下几件事情：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;调用当前进程中的ProcessState单例的成员函数startThreadPool来启动一个Binder线程池，将线程池最大数量设为4，并且调用当前线程中的IPCThreadState单例来将当前线程加入到前面所启动的Binder线程池中去；&lt;/li&gt;
&lt;li&gt;创建一个SurfaceFlinger的对象，并赋给他的强引用指针；&lt;/li&gt;
&lt;li&gt;执行SurfaceFlinger的init函数；&lt;/li&gt;
&lt;li&gt;将SurfaceFlinger服务注册到ServiceManager当中；&lt;/li&gt;
&lt;li&gt;运行SurfaceFlinger的UI渲染流程。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;比较重要的步骤就是创建SurfaceFlinger对象，执行init函数，和运行UI渲染流程。我们逐个分析。&lt;/p&gt;
&lt;h3 id=&quot;创建SurfaceFlinger对象&quot;&gt;&lt;a href=&quot;#创建SurfaceFlinger对象&quot; class=&quot;headerlink&quot; title=&quot;创建SurfaceFlinger对象&quot;&gt;&lt;/a&gt;创建SurfaceFlinger对象&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;new一个SurfaceFlinger对象，并赋给强引用指针。我们先看看它的构造函数，位于frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;SurfaceFlinger::SurfaceFlinger()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    :   BnSurfaceComposer(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mTransactionFlags(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mTransactionPending(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mAnimTransactionPending(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mLayersRemoved(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mRepaintEverything(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mRenderEngine(&lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mBootTime(systemTime()),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mVisibleRegionsDirty(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mHwWorkListDirty(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mAnimCompositionPending(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mDebugRegion(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mDebugDDMS(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mDebugDisableHWC(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mDebugDisableTransformHint(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mDebugInSwapBuffers(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mLastSwapBufferTime(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mDebugInTransaction(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mLastTransactionTime(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mBootFinished(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mPrimaryHWVsyncEnabled(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;span class=&quot;comment&quot;&gt;//主显屏硬件VSync信号关闭&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mHWVsyncAvailable(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mDaltonize(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mHasColorMatrix(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGI(&lt;span class=&quot;string&quot;&gt;&quot;SurfaceFlinger is starting&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//一些调试变量，忽略一下内容&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// debugging stuff...&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; value[PROPERTY_VALUE_MAX];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    property_get(&lt;span class=&quot;string&quot;&gt;&quot;ro.bq.gpu_to_cpu_unsupported&quot;&lt;/span&gt;, value, &lt;span class=&quot;string&quot;&gt;&quot;0&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mGpuToCpuSupported = !atoi(value);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    property_get(&lt;span class=&quot;string&quot;&gt;&quot;debug.sf.showupdates&quot;&lt;/span&gt;, value, &lt;span class=&quot;string&quot;&gt;&quot;0&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDebugRegion = atoi(value);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    property_get(&lt;span class=&quot;string&quot;&gt;&quot;debug.sf.ddms&quot;&lt;/span&gt;, value, &lt;span class=&quot;string&quot;&gt;&quot;0&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDebugDDMS = atoi(value);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mDebugDDMS) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!startDdmConnection()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// start failed, and DDMS debugging not enabled&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mDebugDDMS = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGI_IF(mDebugRegion, &lt;span class=&quot;string&quot;&gt;&quot;showupdates enabled&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGI_IF(mDebugDDMS, &lt;span class=&quot;string&quot;&gt;&quot;DDMS debugging enabled&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;构造函数中主要初始化一系列变量，没什么重要信息。SurfaceFlinger类继承了BnSurfaceComposer类，而后者是一个实现了ISurfaceComposer接口的Binder本地对象类。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;由于Service Manager的Binder代理对象的成员函数addService的第二个参数是一个类型为IBinder的强指针引用。当一个对象第一次被一个强指针引用时，那么这个对象的成员函数onFirstRef就会被调用。因此，接下来前面所创建的SurfaceFlinger实例的成员函数onFirstRef就会被调用，以便可以继续执行初始化操作。我们继续查看：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// mEventQueue在SurfaceFlinger.h中定义&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// these are thread safe&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;mutable&lt;/span&gt; MessageQueue mEventQueue;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::onFirstRef()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEventQueue.init(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;MessageQueue 类在frameworks/native/services/surfaceflinger/MessageQueue.h中定义，实现位于frameworks/native/services/surfaceflinger/MessageQueue.cpp中，init函数如下：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; MessageQueue::init(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;SurfaceFlinger&amp;gt;&amp;amp; flinger)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFlinger = flinger;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mLooper = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Looper(&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mHandler = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Handler(*&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;调用MessageQueue的init，在MessageQueue中建了一个Looper和Handler，注意不是Java中的，native实现的。到后面就可以看到SF的核心就是接收消息，处理消息。对于消息处理，可以参考之前的一片文章&lt;a href=&quot;http://windrunnerlihuan.com/2016/07/31/Android%E6%B6%88%E6%81%AF%E6%9C%BA%E5%88%B6%E9%9B%B6%E6%95%A3%E5%88%86%E6%9E%90/&quot;&gt;Android消息处理零散分析&lt;/a&gt;。&lt;/p&gt;
&lt;h3 id=&quot;调用init函数&quot;&gt;&lt;a href=&quot;#调用init函数&quot; class=&quot;headerlink&quot; title=&quot;调用init函数&quot;&gt;&lt;/a&gt;调用init函数&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;回到SurfaceFlinger.cpp中，继续分析init函数：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;96&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;97&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;98&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;void SurfaceFlinger::init() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGI(  &quot;SurfaceFlinger&#39;s main thread ready to run. &quot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &quot;Initializing graphics H/W...&quot;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    status_t err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::Autolock _l(mStateLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //初始化OpenGL 图形库相关配置&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // initialize EGL for the default display 将EGL初始化成默认的显示，默认是主屏幕，编号为0&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    eglInitialize(mEGLDisplay, NULL, NULL);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //创建显示设备的抽象代表，负责和显示设备打交道&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // Initialize the H/W composer object.  There may or may not be an&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // actual hardware composer underneath.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mHwc = new HWComposer(this,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            *static_cast&amp;lt;HWComposer::EventHandler *&amp;gt;(this));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // get a RenderEngine for the given display / config (can&#39;t fail)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc-&amp;gt;getVisualID());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // retrieve the EGL context that was selected/created&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEGLContext = mRenderEngine-&amp;gt;getEGLContext();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &quot;couldn&#39;t create EGLContext&quot;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // initialize our non-virtual displays&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //创建显示设备对象&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    for (size_t i=0 ; i&amp;lt;DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // set-up the displays that are already connected&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (mHwc-&amp;gt;isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // All non-virtual displays are currently considered secure.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            bool isSecure = true;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            createBuiltinDisplayLocked(type);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            wp&amp;lt;IBinder&amp;gt; token = mBuiltinDisplays[i];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sp&amp;lt;IGraphicBufferProducer&amp;gt; producer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sp&amp;lt;IGraphicBufferConsumer&amp;gt; consumer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            BufferQueue::createBufferQueue(&amp;amp;producer, &amp;amp;consumer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    new GraphicBufferAlloc());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sp&amp;lt;FramebufferSurface&amp;gt; fbs = new FramebufferSurface(*mHwc, i,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    consumer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            int32_t hwcId = allocateHwcDisplayId(type);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sp&amp;lt;DisplayDevice&amp;gt; hw = new DisplayDevice(this,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    type, hwcId, mHwc-&amp;gt;getFormat(hwcId), isSecure, token,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    fbs, producer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    mRenderEngine-&amp;gt;getEGLConfig());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (i &amp;gt; DisplayDevice::DISPLAY_PRIMARY) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // FIXME: currently we don&#39;t get blank/unblank requests&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // for displays other than the main display, so we always&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // assume a connected display is unblanked.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ALOGD(&quot;marking display %zu as acquired/unblanked&quot;, i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                hw-&amp;gt;setPowerMode(HWC_POWER_MODE_NORMAL);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mDisplays.add(token, hw);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // make the GLContext current so that we can create textures when creating Layers&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // (which may happens before we render something)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    getDefaultDisplayDevice()-&amp;gt;makeCurrent(mEGLDisplay, mEGLContext);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // start the EventThread&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //启动EventThread。监听和处理SurfaceFlinger中的事件&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //app的VSync信号&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;VSyncSource&amp;gt; vsyncSrc = new DispSyncSource(&amp;amp;mPrimaryDispSync,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            vsyncPhaseOffsetNs, true, &quot;app&quot;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEventThread = new EventThread(vsyncSrc);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //SF的VSync信号&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;VSyncSource&amp;gt; sfVsyncSrc = new DispSyncSource(&amp;amp;mPrimaryDispSync,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sfVsyncPhaseOffsetNs, true, &quot;sf&quot;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSFEventThread = new EventThread(sfVsyncSrc);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //SF的VSync信号控制逻辑也要放入mEventQueue消息队列&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEventQueue.setEventThread(mSFEventThread);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //VSync信号闸刀控制线程&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEventControlThread = new EventControlThread(this);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEventControlThread-&amp;gt;run(&quot;EventControl&quot;, PRIORITY_URGENT_DISPLAY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // set a fake vsync period if there is no HWComposer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //如果硬件设备检测有问题，或者没有硬件设备驱动提供Vsync信号，则设置软件VSync信号&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (mHwc-&amp;gt;initCheck() != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mPrimaryDispSync.setPeriod(16666667);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // initialize our drawing state&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDrawingState = mCurrentState;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // set initial conditions (e.g. unblank default device)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //初始化显示设备，调用initializeDisplays完成&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    initializeDisplays();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // start boot animation&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //启动开机动画，调用了startBootAnim函数，只是设置了两个属性，其中一个ctl.start是启动了bootanim进程&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    startBootAnim();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;init函数主要做了以下事情：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;初始化OpenGL ES图形库；&lt;/li&gt;
&lt;li&gt;创建显示设备的抽象代表，负责和显示设备打交道；&lt;/li&gt;
&lt;li&gt;创建显示设备对象；&lt;/li&gt;
&lt;li&gt;启动EventThread。监听和处理SurfaceFlinger中的事件；&lt;/li&gt;
&lt;li&gt;设置软件VSync信号周期；&lt;/li&gt;
&lt;li&gt;初始化显示设备，调用initializeDisplays完成；&lt;/li&gt;
&lt;li&gt;启动开机动画，调用了startBootAnim函数，只是设置了两个属性，其中一个ctl.start是启动了bootanim进程。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;其中初始化OpenGL ES可以参考&lt;a href=&quot;http://windrunnerlihuan.com/2017/04/27/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%BA%8C-SurfaceFlinger%E6%A6%82%E8%BF%B0/&quot;&gt;Android SurfaceFlinger 学习之路(二)—-SurfaceFlinger概述&lt;/a&gt;，后期如果有机会再次会细讲。创建显示设备我们后面分析管理图形缓冲区时候会细讲。还有VSync信号，后面会单独开章节分析。这里我们大概过一个流程。&lt;/p&gt;
&lt;h3 id=&quot;执行run函数&quot;&gt;&lt;a href=&quot;#执行run函数&quot; class=&quot;headerlink&quot; title=&quot;执行run函数&quot;&gt;&lt;/a&gt;执行run函数&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后继续往下看，执行SurfaceFlinger的run函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::run() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;do&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        waitForEvent();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::waitForEvent() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEventQueue.waitMessage();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;run函数非常简单，但却是SF的核心，是个while循环，循环处理消息等。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后又调用了EventQueue的waitMessage方法，记住这里是在主线程中循环调用的。&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; MessageQueue::waitMessage() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;do&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//flushCommands主要是清理工作的&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        IPCThreadState::self()-&amp;gt;flushCommands();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//pollOnce是消息机制，主要调用了epoll_wait函数，会阻塞，阻塞完了会分发消息队列中的消息&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; ret = mLooper-&amp;gt;pollOnce(&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt; (ret) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; Looper::POLL_WAKE:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; Looper::POLL_CALLBACK:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; Looper::POLL_ERROR:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;Looper::POLL_ERROR&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; Looper::POLL_TIMEOUT:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// timeout (should not happen)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;default&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// should not happen&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;Looper::pollOnce() returned unknown status %d&quot;&lt;/span&gt;, ret);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们来看下waitMessage方法，flushCommands主要是清理工作的，和Binder驱动的交互关了。而pollOnce是消息机制，主要调用了epoll_wait函数，会阻塞，阻塞完了会分发消息队列中的消息。这里的消息只有自己在Handler中发的消息，还有在setEventThread中自己添加的fd。&lt;/p&gt;
&lt;h2 id=&quot;消息处理&quot;&gt;&lt;a href=&quot;#消息处理&quot; class=&quot;headerlink&quot; title=&quot;消息处理&quot;&gt;&lt;/a&gt;消息处理&lt;/h2&gt;&lt;h3 id=&quot;给SurfaceFlinger发送消息&quot;&gt;&lt;a href=&quot;#给SurfaceFlinger发送消息&quot; class=&quot;headerlink&quot; title=&quot;给SurfaceFlinger发送消息&quot;&gt;&lt;/a&gt;给SurfaceFlinger发送消息&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们以SurfaceFlinger与客户端通信创建Surface为例，看看如何给SurfaceFlinger发送消息。这个我们下面会讲到，这里先举个栗子。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从上一篇开机动画的简述流程可以得知，BootAnimation的readyToRun函数中有一句：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// create the native surface&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//调用SurfaceComposerClient对象mSession的成员函数createSurface可以获得一个SurfaceControl对象control&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;sp&amp;lt;SurfaceControl&amp;gt; control = session()-&amp;gt;createSurface(String8(&lt;span class=&quot;string&quot;&gt;&quot;BootAnimation&quot;&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;BootAnimation类的成员函数session用来返回BootAnimation类的成员变量mSession所描述的一个SurfaceComposerClient对象。通过调用SurfaceComposerClient对象mSession的成员函数createSurface可以获得一个SurfaceControl对象control。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceComposerClient类的成员函数createSurface首先调用内部的Binder代理对象mClient(frameworks/native/services/surfaceflinger/Client.cpp)来请求SurfaceFlinger返回一个类型为(class Handle : public BBinder, public LayerCleaner)Binder代理对象（封装了SurfaceFlinger的sp指针和Layer对象）handle，和一个IGraphicBufferProducer的sp指针（封装了SurfaceFlinger的sp指针）gbp，接着再使用这两个对象来创建一个SurfaceControl对象。创建出来的SurfaceControl对象的成员变量handle就指向了从SurfaceFlinger返回来的类型为Handle 的Binder代理对象。有了这个Binder代理对象之后，SurfaceControl对象就可以和SurfaceFlinger服务通信了。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们关注的就是Client的createSurface函数，frameworks/native/services/surfaceflinger/Client.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; Client::createSurface(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; String8&amp;amp; name,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; h, PixelFormat format, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;IBinder&amp;gt;* handle,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;IGraphicBufferProducer&amp;gt;* gbp)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * createSurface must be called from the GL thread so that it can&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * have access to the GL context.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; MessageCreateLayer : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; MessageBase &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        SurfaceFlinger* flinger;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Client* client;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;IBinder&amp;gt;* handle;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;IGraphicBufferProducer&amp;gt;* gbp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; result;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; String8&amp;amp; name;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; w, h;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PixelFormat format;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        MessageCreateLayer(SurfaceFlinger* flinger,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; String8&amp;amp; name, Client* client,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; h, PixelFormat format, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                sp&amp;lt;IBinder&amp;gt;* handle,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                sp&amp;lt;IGraphicBufferProducer&amp;gt;* gbp)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            : flinger(flinger), client(client),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              handle(handle), gbp(gbp),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              name(name), w(w), h(h), format(format), flags(flags) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; getResult() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &amp;#123; &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; result; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//handler是执行消息动作的地方&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            result = flinger-&amp;gt;createLayer(name, client, w, h, format, flags,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    handle, gbp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//首先封装消息&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;MessageBase&amp;gt; msg = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; MessageCreateLayer(mFlinger.get(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            name, &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;, w, h, format, flags, handle, gbp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//调用SF的postMessageSync发送同步消息&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFlinger-&amp;gt;postMessageSync(msg);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;MessageCreateLayer*&amp;gt;( msg.get() )-&amp;gt;getResult();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;类MessageBase就是封装了类似于一个Handler，里面有个Barrier，我们能够猜到，这个Barrier 肯定是用来进行同步发送消息的，利用Barrier 去等待”wait”。位于framework/native/services/surfaceflinger/MessageQueue.h中:&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; MessageBase : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; MessageHandler&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    MessageBase();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// return true if message has a handler&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// waits for the handler to be processed&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;/span&gt;&amp;#123; barrier.wait(); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; ~MessageBase();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;handleMessage&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Message&amp;amp; message)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;mutable&lt;/span&gt; Barrier barrier;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;MessageBase的handleMessage函数，可以看到MessageBase的handler()函数是真正消息处理的地方，执行完成后，调用barrier.open();，打开barrier，这样调用barrier.wait()的地方就能退出了。实现位于framework/native/services/surfaceflinger/MessageQueue.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; MessageBase::handleMessage(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Message&amp;amp;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;-&amp;gt;handler();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    barrier.open();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接着分析mFlinger-&amp;gt;postMessageSync(msg);，这是给SF发同步消息的入口，当然也可以发异步消息，实现是类似的:&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; SurfaceFlinger::postMessageSync(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;MessageBase&amp;gt;&amp;amp; msg,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; reltime, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;comment&quot;&gt;/* flags */&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//向mEventQueue，即MessageQueue中发送消息&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; res = mEventQueue.postMessage(msg, reltime);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//这里等着，同步就在同步函数中等着&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (res == NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        msg-&amp;gt;wait();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; res;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;可以看到在同步发送消息中，barrier在postMessageSync函数中一直等着呢（wait），等待SF调用handleMessage()函数去将barrier这个栅栏打开(open)。&lt;/p&gt;
&lt;h3 id=&quot;SurfaceFlinger处理消息&quot;&gt;&lt;a href=&quot;#SurfaceFlinger处理消息&quot; class=&quot;headerlink&quot; title=&quot;SurfaceFlinger处理消息&quot;&gt;&lt;/a&gt;SurfaceFlinger处理消息&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从上面waitMessage得知，消息处理都位于里面无限循环处的的int32_t ret = mLooper-&amp;gt;pollOnce(-1);我们追寻到Looper中的pollOnce函数，位于system/core/libutils/Looper.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; Looper::pollOnce(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; timeoutMillis, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;* outFd, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;* outEvents, &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;** outData) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; result = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (;;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        result = pollInner(timeoutMillis);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数中，而pollOnce又会调用pollInner：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; Looper::pollInner(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; timeoutMillis) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;// Invoke pending message callbacks.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mNextMessageUptime = LLONG_MAX;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (mMessageEnvelopes.size() != &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; now = systemTime(SYSTEM_TIME_MONOTONIC);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; MessageEnvelope&amp;amp; messageEnvelope = mMessageEnvelopes.itemAt(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (messageEnvelope.uptime &amp;lt;= now) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// Remove the envelope from the list.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// We keep a strong reference to the handler until the call to handleMessage&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// finishes.  Then we drop it so that the handler can be deleted *before*&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// we reacquire our lock.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#123; &lt;span class=&quot;comment&quot;&gt;// obtain handler&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                sp&amp;lt;MessageHandler&amp;gt; handler = messageEnvelope.handler;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                Message message = messageEnvelope.message;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//把头删除啊&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mMessageEnvelopes.removeAt(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mSendingMessage = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mLock.unlock();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ALOGD(&lt;span class=&quot;string&quot;&gt;&quot;%p ~ pollOnce - sending message: handler=%p, what=%d&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;, handler.get(), message.what);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//处理消息啊&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                handler-&amp;gt;handleMessage(message);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;comment&quot;&gt;// release handler&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mLock.lock();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSendingMessage = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            result = ALOOPER_POLL_CALLBACK;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// The last message left at the head of the queue determines the next wakeup time.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mNextMessageUptime = messageEnvelope.uptime;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从上面代码可以看到，发给SF的消息被封装在MessageEnvelope结构中，SF一直在mMessageEnvelopes队列中从头部取出消息，然后执行，即handler-&amp;gt;handleMessage(message)，这个即是我们上面提到的framework/native/services/surfaceflinger/MessageQueue.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; MessageBase::handleMessage(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Message&amp;amp;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;-&amp;gt;handler();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//打开栅栏&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    barrier.open();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;调用handleMessage执行handler()，所以SurfaceFlinger创建Surface的核心代码就是SurfaceFlinger的createLayer函数，回到刚才的createSurface函数中的片段：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;result = flinger-&amp;gt;createLayer(name, client, w, h, format, flags,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    handle, gbp);&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;执行完成后，打开barrier。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个只是个简单例子，我们后续会详细讲解它的消息处理流程。&lt;/p&gt;
&lt;h1 id=&quot;SurfaceFlinger服务连接过程&quot;&gt;&lt;a href=&quot;#SurfaceFlinger服务连接过程&quot; class=&quot;headerlink&quot; title=&quot;SurfaceFlinger服务连接过程&quot;&gt;&lt;/a&gt;SurfaceFlinger服务连接过程&lt;/h1&gt;&lt;h2 id=&quot;概述&quot;&gt;&lt;a href=&quot;#概述&quot; class=&quot;headerlink&quot; title=&quot;概述&quot;&gt;&lt;/a&gt;概述&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;第一篇文章描述Android应用程序和SurfaceFlinger服务的关系时提到，每一个有UI的Android应用程序都需要与SurfaceFlinger服务建立一个连接，以便可以通过这个连接来请求SurfaceFlinger服务为它创建和渲染Surface。我们将以Android系统的开机动画应用程序为例，详细描述Android应用程序是如何与SurfaceFlinger服务建立连接的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从从上一篇文章可以知道，Android系统的开机动画是主要一个BootAnimation对象来实现，这个BootAnimation对象在构造的时候，会在内部创建一个SurfaceComposerClient对象来负责创建一个到SurfaceFlinger服务的连接。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;BootAnimation类的构造函数实现在文件frameworks/base/cmds/bootanimation/BootAnimation.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;BootAnimation::BootAnimation() : Thread(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;), mZip(&lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSession = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; SurfaceComposerClient();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;mSession是BootAnimation类的成员变量，它是一个类型为SurfaceComposerClient的强指针，即sp &amp;lt; SurfaceComposerClient &amp;gt; 。在SurfaceComposerClient类内部，有一个类型为sp&amp;lt; ISurfaceComposerClient &amp;gt;的成员变量mClient，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%9B%9B%29----SurfaceFlinger%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%90%AF%E5%8A%A8%E4%B8%8E%E8%BF%9E%E6%8E%A5%E8%BF%87%E7%A8%8B/SurfaceComposerClient.jpg&quot; alt=&quot;SurfaceComposerClient&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceComposerClient类的成员变量mClient指向的实际上是一个类型为BpSurfaceComposerClient的Binder代理对象，而这个类型为BpSurfaceComposerClient的Binder代理对象引用的是一个类型为Client的Binder本地对象，位于frameworks/native/services/surfaceflinger/Client.cpp。&lt;strong&gt;类型为Client的Binder本地对象是由SurfaceFlinger服务来负责创建的，并且运行在SurfaceFlinger服务中，用来代表使用SurfaceFlinger服务的一个客户端，即一个与UI相关的Android应用程序&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;由于Client类和BpSurfaceComposerClient类分别是一个Binder本地对象类和一个Binder代理对象类，它们都是根据Android系统在应用程序框架层提供的Binder进程间通信库来实现的。类图如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%9B%9B%29----SurfaceFlinger%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%90%AF%E5%8A%A8%E4%B8%8E%E8%BF%9E%E6%8E%A5%E8%BF%87%E7%A8%8B/Client.jpg&quot; alt=&quot;Client&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Client类的实现结构图&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%9B%9B%29----SurfaceFlinger%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%90%AF%E5%8A%A8%E4%B8%8E%E8%BF%9E%E6%8E%A5%E8%BF%87%E7%A8%8B/BpSurfaceComposerClient.jpg&quot; alt=&quot;BpSurfaceComposerClient&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;BpSurfaceComposerClient类的实现结构图&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Client类和BpSurfaceComposerClient类均实现了类型为ISurfaceComposerClient的Binder接口。ISurfaceComposerClient接口有个createSurface接口，它们定义在文件frameworks/base/include/surfaceflinger/ISurfaceComposerClient.h中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; ISurfaceComposerClient : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; IInterface&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * Requires ACCESS_SURFACE_FLINGER permission&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; status_t &lt;span class=&quot;title&quot;&gt;createSurface&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; String8&amp;amp; name, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; h,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            PixelFormat format, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sp&amp;lt;IBinder&amp;gt;* handle,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            sp&amp;lt;IGraphicBufferProducer&amp;gt;* gbp)&lt;/span&gt; &lt;/span&gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在接下来的文章中，我们再详细分析ISurfaceComposerClient接口的成员函数createSurface的实现。&lt;/p&gt;
&lt;p&gt;理解了SurfaceComposerClient、Client以及BpSurfaceComposerClient这三个类的关系之后，接下来我们就可以分析Android系统的开机动画应用程序bootanimation是如何与SurfaceFlinger服务建立连接的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceComposerClient类继承了RefBase类，因此，当BootAnimation类在构造函数创建了一个SurfaceComposerClient对象，并且将这个对象赋值给类型为sp&amp;lt; SurfaceComposerClient &amp;gt;的智能指针mSession时，就会导致SurfaceComposerClient类的成员函数onFirstRef被调用，而SurfaceComposerClient类的成员函数onFirstRef在调用的过程中，就会在应用程序bootanimation与SurfaceFlinger服务建立一个连接。这个流程如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%9B%9B%29----SurfaceFlinger%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%90%AF%E5%8A%A8%E4%B8%8E%E8%BF%9E%E6%8E%A5%E8%BF%87%E7%A8%8B/connection.jpg&quot; alt=&quot;Android应用程序与SurfaceFlinger服务的连接过程&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接下来，我们就详细分析每一个步骤。&lt;/p&gt;
&lt;h2 id=&quot;获取SurfaceFlinger服务代理接口&quot;&gt;&lt;a href=&quot;#获取SurfaceFlinger服务代理接口&quot; class=&quot;headerlink&quot; title=&quot;获取SurfaceFlinger服务代理接口&quot;&gt;&lt;/a&gt;获取SurfaceFlinger服务代理接口&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;进入frameworks/native/libs/gui/SurfaceComposerClient.cpp中，找到onFristRef函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceComposerClient::onFirstRef() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;ISurfaceComposer&amp;gt; sm(ComposerService::getComposerService());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (sm != &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;ISurfaceComposerClient&amp;gt; conn = sm-&amp;gt;createConnection();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (conn != &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mClient = conn;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mStatus = NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceComposerClient类的成员函数getComposerService用来获得SurfaceFlinger服务的一个代理接口，它的实现同样位于frameworks/native/libs/gui/SurfaceComposerClient.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/*static*/&lt;/span&gt; sp&amp;lt;ISurfaceComposer&amp;gt; ComposerService::getComposerService() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ComposerService&amp;amp; instance = ComposerService::getInstance();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::Autolock _l(instance.mLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (instance.mComposerService == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ComposerService::getInstance().connectLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        assert(instance.mComposerService != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGD(&lt;span class=&quot;string&quot;&gt;&quot;ComposerService reconnected&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; instance.mComposerService;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;ComposerService类是单例模式，当我们第一次调用它的静态函数getInstance的时候，它就会在构造函数中获得SurfaceFlinger服务的一个代理接口，并且保存在它的成员变量mComposerService中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;ComposerService::ComposerService()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;: Singleton&amp;lt;ComposerService&amp;gt;() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::Autolock _l(mLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    connectLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; ComposerService::connectLocked() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; String16 &lt;span class=&quot;title&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;string&quot;&gt;&quot;SurfaceFlinger&quot;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (getService(name, &amp;amp;mComposerService) != NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        usleep(&lt;span class=&quot;number&quot;&gt;250000&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    assert(mComposerService != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Create the death listener.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; DeathObserver : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; IBinder::DeathRecipient &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ComposerService&amp;amp; mComposerService;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;binderDied&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; wp&amp;lt;IBinder&amp;gt;&amp;amp; who)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ALOGW(&lt;span class=&quot;string&quot;&gt;&quot;ComposerService remote (surfaceflinger) died [%p]&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                  who.unsafe_get());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mComposerService.composerServiceDied();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        DeathObserver(ComposerService&amp;amp; mgr) : mComposerService(mgr) &amp;#123; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDeathObserver = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; DeathObserver(*&lt;span class=&quot;keyword&quot;&gt;const_cast&lt;/span&gt;&amp;lt;ComposerService*&amp;gt;(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mComposerService-&amp;gt;asBinder()-&amp;gt;linkToDeath(mDeathObserver);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在ComposerService类的构造函数中，会获得SurfaceFlinger服务的代理接口。&lt;/p&gt;
&lt;h2 id=&quot;连接SurfaceFlinger服务&quot;&gt;&lt;a href=&quot;#连接SurfaceFlinger服务&quot; class=&quot;headerlink&quot; title=&quot;连接SurfaceFlinger服务&quot;&gt;&lt;/a&gt;连接SurfaceFlinger服务&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;回到SurfaceComposerClient类的成员函数onFirstRef中，由于SurfaceFlinger服务实现了ISurfaceComposer接口，因此，我们可以将前面获得的SurfaceFlinger服务的代理接口赋值给一个类型为ISurfaceComposer的强指针sm，并且调用它的成员函数createConnection来请求SurfaceFlinger服务创建一个连接，即创建一个类型为Client的Binder对象，并且将这个Binder对象的一个代理接口conn返回来。SurfaceComposerClient类获得了SurfaceFlinger服务返回来的Client代理接口conn之后，就将它保存自己的成员变量mClient中，这样开机动画应用程序bootanimation后续就可以通过它来请求SurfaceFlinger创建和渲染Surface了。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接下来，我们就继续分析SurfaceFlinger服务的成员函数createConnection的实现，以便可以了解它是如何为Android应用程序创建一个连接的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;进入SurfaceFlinger.cpp中查看createConnection函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sp&amp;lt;ISurfaceComposerClient&amp;gt; SurfaceFlinger::createConnection()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;ISurfaceComposerClient&amp;gt; bclient;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;Client&amp;gt; client(&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Client(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = client-&amp;gt;initCheck();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        bclient = client;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; bclient;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;它的实现很简单，只是创建了一个类型为Client的Binder对象client，并且获得它的一个ISurfaceComposerClient接口，最后将这个ISurfaceComposerClient接口，即一个Client代理对象，返回给开机动画应用程序bootanimation。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接下来，我们再继续分析Client对象的创建过程,，即Client类的构造函数的实现：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;Client::Client(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;SurfaceFlinger&amp;gt;&amp;amp; flinger)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    : mFlinger(flinger)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个很简单，就是保存了SurfaceFlinger的强引用对象。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;回到SurfaceFlinger类的成员函数createConnection中，它将一个指向了一个Client对象的ISurfaceComposerClient接口返回到开机动画应用程序bootanimation之后，开机动画应用程序bootanimation就可以将它封装成一个类型为BpSurfaceComposerClient的Binder代理对象。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;类型为BpSurfaceComposerClient的Binder代理对象的封装过程实现在SurfaceFlinger服务的Binder代理对象类BpSurfaceComposer的成员函数createConnection中，位于frameworks/native/libs/gui/ISurfaceCompose.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; BpSurfaceComposer : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; BpInterface&amp;lt;ISurfaceComposer&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; sp&amp;lt;ISurfaceComposerClient&amp;gt; createConnection()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; n;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Parcel data, reply;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        remote()-&amp;gt;transact(BnSurfaceComposer::CREATE_CONNECTION, data, &amp;amp;reply);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; interface_cast&amp;lt;ISurfaceComposerClient&amp;gt;(reply.readStrongBinder());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;interface_cast是一个模板函数，它定义在framework/native/include/binder/IInterface.h文件中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; INTERFACE&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;inline&lt;/span&gt; sp&amp;lt;INTERFACE&amp;gt; interface_cast(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;IBinder&amp;gt;&amp;amp; obj)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; INTERFACE::asInterface(obj);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从这里就可以看出，当模板参数为ISurfaceComposerClient的时候，模板函数interface_cast实际就是通过调用ISurfaceComposerClient类的静态成员函数asInterface来将参数obj所描述的一个Binder代理对象，即一个BpBinder对象，封装成一个BpSurfaceComposerClient对象。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;ISurfaceComposerClient类的静态成员函数asInterface是由frameworks/native/libs/gui/ISurfaceComposerClient.cpp文件中的IMPLEMENT_META_INTERFACE宏来定义的，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;IMPLEMENT_META_INTERFACE(SurfaceComposerClient, &lt;span class=&quot;string&quot;&gt;&quot;android.ui.ISurfaceComposerClient&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;IMPLEMENT_META_INTERFACE宏展开后，得到ISurfaceComposerClient类的静态成员函数asInterface的实现如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;android::sp&amp;lt;ISurfaceComposerClient&amp;gt; ISurfaceComposerClient::asInterface(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; android::sp&amp;lt;android::IBinder&amp;gt;&amp;amp; obj)       &amp;#123;                                                                                         &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    android::sp&amp;lt;ISurfaceComposerClient&amp;gt; intr;                                                        &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (obj != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;                                                                         &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        intr = &lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;ISurfaceComposerClient*&amp;gt;(                                                      &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    obj-&amp;gt;queryLocalInterface(ISurfaceComposerClient::descriptor).get());    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (intr == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;                    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            intr = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; BpSurfaceComposerClient(obj);                                            &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;                                              &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ｝    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; intr;                                      &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;参数obj是从BpSurfaceComposer类的成员函数createConnection传进来的，它指向的实际上是一个BpBinder对象。当我们调用一个BpBinder对象的成员函数queryLocalInterface时，获得的是一个NULL指针，因此，ISurfaceComposerClient类的静态成员函数asInterface最后就会将参数obj所指向的一个BpBinder对象封装成一个BpSurfaceComposerClient对象，并且返回给调用者。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;至此，开机动画应用程序bootanimation就通过SurfaceComposerClient类来与SurfaceFlinger服务建立一个连接了。&lt;/p&gt;
&lt;h1 id=&quot;小结&quot;&gt;&lt;a href=&quot;#小结&quot; class=&quot;headerlink&quot; title=&quot;小结&quot;&gt;&lt;/a&gt;小结&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;本篇主要学习了SurfaceFlinger的启动和连接过程，应该算不太难的部分。下几节我们将逐步分析消息处理、创建surface、管理GraphicBuffer、VSync信号、Fence机制等等内容。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E5%9B%9B%29----SurfaceFlinger%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%90%AF%E5%8A%A8%E4%B8%8E%E8%BF%9E%E6%8E%A5%E8%BF%87%E7%A8%8B/mezi.jpg&quot; alt=&quot;妹子&quot;&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上一篇我们分析了Android的开机动画启动流程，这一篇我们基于上一篇的基础，分析一下SurfaceFlinger的启动，还有连接它的过程。&lt;br&gt;
    
    </summary>
    
      <category term="Android技术点" scheme="http://windrunnerlihuan.com/categories/Android%E6%8A%80%E6%9C%AF%E7%82%B9/"/>
    
    
      <category term="SurfaceFlinger" scheme="http://windrunnerlihuan.com/tags/SurfaceFlinger/"/>
    
  </entry>
  
  <entry>
    <title>Android SurfaceFlinger 学习之路(三)----Android开机动画流程简述</title>
    <link href="http://windrunnerlihuan.com/2017/05/02/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B8%89-Android%E5%BC%80%E6%9C%BA%E5%8A%A8%E7%94%BB%E6%B5%81%E7%A8%8B%E7%AE%80%E8%BF%B0/"/>
    <id>http://windrunnerlihuan.com/2017/05/02/Android-SurfaceFlinger-学习之路-三-Android开机动画流程简述/</id>
    <published>2017-05-02T09:28:11.000Z</published>
    <updated>2019-01-06T07:28:06.176Z</updated>
    
    <content type="html">&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在详细分析SurfaceFlinger模块之前要先看看Android的开机动画，因为这个BootAnimation是一个C++应用程序，需要使用SurfaceFlinger服务来创建和渲染自己的Surface，并且不涉及与用户进行交互，所以能以最简洁的方式体现Android与SurfaceFlinger服务的关系。&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;开机动画的启动&quot;&gt;&lt;a href=&quot;#开机动画的启动&quot; class=&quot;headerlink&quot; title=&quot;开机动画的启动&quot;&gt;&lt;/a&gt;开机动画的启动&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;第一个开机画面是在内核启动的过程中出现的，它是一个静态的画面。第二个开机画面是在init进程启动的过程中出现的，它也是一个静态的画面。第三个开机画面BootAnimation是在系统服务启动的过程中出现的，它是一个动态的画面。无论是哪一个画面，它们都是在一个称为帧缓冲区（frame buffer，简称fb）的硬件设备上进行渲染的。接下来，我们就分别分析第三个画面是如何在fb上显示的。&lt;/p&gt;
&lt;h2 id=&quot;bootanimation的启动过程&quot;&gt;&lt;a href=&quot;#bootanimation的启动过程&quot; class=&quot;headerlink&quot; title=&quot;bootanimation的启动过程&quot;&gt;&lt;/a&gt;bootanimation的启动过程&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;第三个开机动画使用应用程序BootAnimation来负责显示的，它在启动脚本init.rc中被配置成了一个服务，位于system/core/rootdir/Init.rc：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;service bootanim /system/bin/bootanimation&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; core&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    user graphics &lt;span class=&quot;comment&quot;&gt;//用户&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    group graphics audio &lt;span class=&quot;comment&quot;&gt;//用户组&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    disabled &lt;span class=&quot;comment&quot;&gt;//init进程启动时，不会自动启动bootanimation&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    oneshot&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;......&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;应用程序bootanimation的用户和用户组名称分别被设置为graphics。注意， 用来启动应用程序bootanimation的服务是disable的，即init进程在启动的时候，不会主动将应用程序bootanimation启动起来。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当SurfaceFlinger服务启动的时候，它会通过修改系统属性ctl.start的值来通知init进程启动应用程序bootanimation，以便可以显示第三个开机画面。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在早期的Android版本中，SurfaceFlinger服务是由SystemServer启动的。但在Android5.0中，该服务是init进程启动过程中就启动了。在init.rc中能看到对该服务的描述：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;service surfaceflinger /system/bin/surfaceflinger&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; core&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    user system&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    group graphics drmrpc&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    onrestart restart zygote&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;......&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceFlinger服务的源码路径位于framework/native/services/surfaceflinger/下面，服务的入口在下面的main_surfaceflinger.cpp中，我们查看它的main函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt;**)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// When SF is launched in its own process, limit the number of&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// binder threads to 4.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ProcessState::self()-&amp;gt;setThreadPoolMaxThreadCount(&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// start the thread pool&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;ProcessState&amp;gt; ps(ProcessState::self());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ps-&amp;gt;startThreadPool();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// instantiate surfaceflinger&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;SurfaceFlinger&amp;gt; flinger = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; SurfaceFlinger();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; defined(HAVE_PTHREADS)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    setpriority(PRIO_PROCESS, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, PRIORITY_URGENT_DISPLAY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    set_sched_policy(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, SP_FOREGROUND);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// initialize before clients can connect&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    flinger-&amp;gt;init(); &lt;span class=&quot;comment&quot;&gt;//我们主要看这里，其他忽略&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// publish surface flinger&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;IServiceManager&amp;gt; sm(defaultServiceManager());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sm-&amp;gt;addService(String16(SurfaceFlinger::getServiceName()), flinger, &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// run in this thread&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    flinger-&amp;gt;run();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;主要工作就是新建一个SurfaceFlinger对象，然后调用其中的init函数，最后调用run函数。我们的重点在init方法，位于framework/native/services/surfaceflinger/SurfaceFlinger.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::init() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;...省略大量代码...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// start boot animation&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    startBootAnim();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;最后一行调用了startBootAnim函数，我们继续往下看：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::startBootAnim() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// start boot animation&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    property_set(&lt;span class=&quot;string&quot;&gt;&quot;service.bootanim.exit&quot;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&quot;0&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    property_set(&lt;span class=&quot;string&quot;&gt;&quot;ctl.start&quot;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&quot;bootanim&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里讲系统属性”service.bootanim.exit”设置为”0”，并将”ctl.start”设置为”bootanim”。重点是第二个。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;当系统属性发生改变时，init进程就会接收到一个系统属性变化通知，这个通知最终是由在init进程中的函数handle_property_set_fd来处理的&lt;/strong&gt;。我们可以查看init进程的入口main函数，位于system/core/init/Init.c中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; argc, &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; **argv)&lt;/span&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;...省略大量代码...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt;(;;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; nr, i, timeout = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ...省略一些代码...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//poll函数用来轮询事件&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        nr = poll(ufds, fd_count, timeout);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (nr &amp;lt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; fd_count; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ufds[i].revents &amp;amp; POLLIN) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//我们关注这里，当系统属性值被修改时，得到该事件，会执行handle_property_set_fd函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ufds[i].fd == get_property_set_fd())&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    handle_property_set_fd();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ufds[i].fd == get_keychord_fd())&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    handle_keychord();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ufds[i].fd == get_signal_fd())&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    handle_signal();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;可以看到，init进程会使用poll机制来轮询事件，其中一个事件是系统属性值被修改。得到该事件后，会执行handle_property_set_fd()，位于system/core/init/Property_service.c中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;96&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;97&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;98&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;99&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;100&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;101&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;102&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;103&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;104&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;105&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;handle_property_set_fd&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    prop_msg msg; &lt;span class=&quot;comment&quot;&gt;//init进程是通过一个socket来接收系统属性变化事件的&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; s;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; r;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; res;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; ucred cr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; sockaddr_un addr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;socklen_t&lt;/span&gt; addr_size = &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(addr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;socklen_t&lt;/span&gt; cr_size = &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(cr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; * source_ctx = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; pollfd ufds[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; timeout_ms = &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt; * &lt;span class=&quot;number&quot;&gt;1000&lt;/span&gt;;  &lt;span class=&quot;comment&quot;&gt;/* Default 2 sec timeout for caller to send property. */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; nr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//接收TCP连接 服务端阻塞？等待客户端连接&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((s = accept(property_set_fd, (&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; sockaddr *) &amp;amp;addr, &amp;amp;addr_size)) &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* Check socket options here */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//取出socket的可选内容，可能包括客户端进程的权限等属性 &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &amp;amp;cr, &amp;amp;cr_size) &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        close(s); &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ERROR(&lt;span class=&quot;string&quot;&gt;&quot;Unable to receive socket options\n&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ufds[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].fd = s;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ufds[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].events = POLLIN;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ufds[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].revents = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//轮询客户端事件&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    nr = TEMP_FAILURE_RETRY(poll(ufds, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, timeout_ms));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//轮询事件超时&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (nr == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ERROR(&lt;span class=&quot;string&quot;&gt;&quot;sys_prop: timeout waiting for uid=%d to send property message.\n&quot;&lt;/span&gt;, cr.uid);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        close(s);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//等待错误&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (nr &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ERROR(&lt;span class=&quot;string&quot;&gt;&quot;sys_prop: error waiting for uid=%d to send property message. err=%d %s\n&quot;&lt;/span&gt;, cr.uid, errno, strerror(errno));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        close(s);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//接收socket的主体数据 &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    r = TEMP_FAILURE_RETRY(recv(s, &amp;amp;msg, &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(msg), MSG_DONTWAIT));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//接收事件不匹配，return&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt;(r != &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(prop_msg)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ERROR(&lt;span class=&quot;string&quot;&gt;&quot;sys_prop: mis-match msg size received: %d expected: %zu errno: %d\n&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              r, &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(prop_msg), errno);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        close(s);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//开始条件判断接收事件&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt;(msg.cmd) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; PROP_MSG_SETPROP: &lt;span class=&quot;comment&quot;&gt;//如果是属性发生变化&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        msg.name[PROP_NAME_MAX&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;] = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        msg.value[PROP_VALUE_MAX&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;] = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//检查属性名，不能有特殊字符，或者两个点..这样的名字&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!is_legal_property_name(msg.name, &lt;span class=&quot;built_in&quot;&gt;strlen&lt;/span&gt;(msg.name))) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ERROR(&lt;span class=&quot;string&quot;&gt;&quot;sys_prop: illegal property name. Got: \&quot;%s\&quot;\n&quot;&lt;/span&gt;, msg.name);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            close(s);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        getpeercon(s, &amp;amp;source_ctx);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/* &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        如果是ctl开头的消息，则认为是控制消息，控制消息用来执行一些命令，例如用adb shell登录后，输入setprop ctl.start bootanim就可以查看开机动画了;输入setprop service.bootanim.exit 1就可以退出开机动画了&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    */&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt;(&lt;span class=&quot;built_in&quot;&gt;memcmp&lt;/span&gt;(msg.name,&lt;span class=&quot;string&quot;&gt;&quot;ctl.&quot;&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;) == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// Keep the old close-socket-early behavior when handling&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// ctl.* properties.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            close(s);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//改变系统属性是需要权限,所以需要减产是否有权限&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (check_control_mac_perms(msg.value, source_ctx)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//通过了权限检查之后，另外一个函数handle_control_message就会被调用，以便可以执行一个名称为“bootanim”的命令&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                handle_control_message((&lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt;*) msg.name + &lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;, (&lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt;*) msg.value);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ERROR(&lt;span class=&quot;string&quot;&gt;&quot;sys_prop: Unable to %s service ctl [%s] uid:%d gid:%d pid:%d\n&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        msg.name + &lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;, msg.value, cr.uid, cr.gid, cr.pid);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;         &lt;span class=&quot;comment&quot;&gt;/* &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            不是ctl开头的属性，则首先检查其权限。例如，设置net.开头的属性需要AID_SYSTEM权限，log.开头的属性需要AID_SHELL属性等。 &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        */&lt;/span&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (check_perms(msg.name, source_ctx)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// 最后通过property_set函数设置客户端需要设置的属性  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                property_set((&lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt;*) msg.name, (&lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt;*) msg.value);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ERROR(&lt;span class=&quot;string&quot;&gt;&quot;sys_prop: permission denied uid:%d  name:%s\n&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                      cr.uid, msg.name);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// Note: bionic&#39;s property client code assumes that the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// property server will not close the socket until *AFTER*&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// the property is written to memory.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            close(s);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        freecon(source_ctx);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;default&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        close(s);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;init进程是通过一个socket来接收系统属性变化事件的。每一个系统属性变化事件的内容都是通过一个prop_msg对象来描述的。在prop_msg对象对，成员变量name用来描述发生变化的系统属性的名称，而成员变量value用来描述发生变化的系统属性的值。系统属性分为两种类型，一种是普通类型的系统属性，另一种是控制类型的系统属性（属性名称以“ctl.”开头）。控制类型的系统属性在发生变化时，会触发init进程执行一个命令，而普通类型的系统属性就不具有这个特性。注意，改变系统属性是需要权限，因此，函数handle_property_set_fd在处理一个系统属性变化事件之前，首先会检查修改系统属性的进程是否具有相应的权限，这是通过调用函数check_control_perms或者check_perms来实现的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从前面的调用过程可以知道，当前发生变化的系统属性的名称为“ctl.start”，它的值被设置为“bootanim”。由于这是一个控制类型的系统属性，因此，在通过了权限检查之后，另外一个函数handle_control_message就会被调用，以便可以执行一个名称为“bootanim”的命令。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数handle_control_message实现在system/core/init/Init.c中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;handle_control_message&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; *msg, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; *arg)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!&lt;span class=&quot;built_in&quot;&gt;strcmp&lt;/span&gt;(msg,&lt;span class=&quot;string&quot;&gt;&quot;start&quot;&lt;/span&gt;)) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//所以进入了这里&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        msg_start(arg);&lt;span class=&quot;comment&quot;&gt;//arg是bootanimation&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!&lt;span class=&quot;built_in&quot;&gt;strcmp&lt;/span&gt;(msg,&lt;span class=&quot;string&quot;&gt;&quot;stop&quot;&lt;/span&gt;)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        msg_stop(arg);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!&lt;span class=&quot;built_in&quot;&gt;strcmp&lt;/span&gt;(msg,&lt;span class=&quot;string&quot;&gt;&quot;restart&quot;&lt;/span&gt;)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        msg_restart(arg);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ERROR(&lt;span class=&quot;string&quot;&gt;&quot;unknown control msg &#39;%s&#39;\n&quot;&lt;/span&gt;, msg);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;控制类型的系统属性的名称是以”ctl.”开头，并且是以“start”或者“stop”结尾的，其中，“start”表示要启动某一个服务，而“stop”表示要停止某一个服务，它们是分别通过函数msg_start和msg_stop来实现的。由于当前发生变化的系统属性是以“start”来结尾的，因此，接下来就会调用函数msg_start来启动一个名称为“bootanim”的服务。 &lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数msg_start实现在文件system/core/init/Init.c中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;msg_start&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; *name)&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//bootanim&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; service *svc = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; *tmp = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; *args = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!&lt;span class=&quot;built_in&quot;&gt;strchr&lt;/span&gt;(name, &lt;span class=&quot;string&quot;&gt;&#39;:&#39;&lt;/span&gt;))&lt;span class=&quot;comment&quot;&gt;//into&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//查找init.rc中配置的service列表&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        svc = service_find_by_name(name);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        tmp = strdup(name);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (tmp) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            args = &lt;span class=&quot;built_in&quot;&gt;strchr&lt;/span&gt;(tmp, &lt;span class=&quot;string&quot;&gt;&#39;:&#39;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            *args = &lt;span class=&quot;string&quot;&gt;&#39;\0&#39;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            args++;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            svc = service_find_by_name(tmp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (svc) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//如果在列表中找到了bootanim，则启动它&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        service_start(svc, args);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ERROR(&lt;span class=&quot;string&quot;&gt;&quot;no such service &#39;%s&#39;\n&quot;&lt;/span&gt;, name);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (tmp)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;built_in&quot;&gt;free&lt;/span&gt;(tmp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;该函数首先调用service_find_by_name()，从service_list中查询要启动的服务是否有存在，若存在，返回服务的相关信息。因为init.rc中有bootanimation的定义，因此在init进程执行parse_config()时，会将该服务添加到service_list中，所以bootanimation应用是存在的。然后，如果找到了该服务，就调用service_start启动服务。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;到此，bootanimation应用就启动了。&lt;/p&gt;
&lt;h2 id=&quot;开机动画显示&quot;&gt;&lt;a href=&quot;#开机动画显示&quot; class=&quot;headerlink&quot; title=&quot;开机动画显示&quot;&gt;&lt;/a&gt;开机动画显示&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从前面的内容可以知道，名称等于“bootanim”的服务所对应的应用程序为/system/bin/bootanimation，这个应用程序实现在frameworks/base/cmds/bootanimation目录中，其中，应用程序入口函数main是实现在frameworks/base/cmds/bootanimation/Bootanimation_main.cpp中的，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; argc, &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt;** argv)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; defined(HAVE_PTHREADS)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    setpriority(PRIO_PROCESS, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, ANDROID_PRIORITY_DISPLAY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; value[PROPERTY_VALUE_MAX];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    property_get(&lt;span class=&quot;string&quot;&gt;&quot;debug.sf.nobootanimation&quot;&lt;/span&gt;, value, &lt;span class=&quot;string&quot;&gt;&quot;0&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; noBootAnimation = atoi(value);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGI_IF(noBootAnimation,  &lt;span class=&quot;string&quot;&gt;&quot;boot animation disabled&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!noBootAnimation) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//检查系统属性“debug.sf.nobootnimaition”的值是否不等于0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//启动一个Binder线程池&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;ProcessState&amp;gt; proc(ProcessState::self());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ProcessState::self()-&amp;gt;startThreadPool();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// create the boot animation object&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//创建一个BootAnimation对象&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;BootAnimation&amp;gt; boot = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; BootAnimation();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        IPCThreadState::self()-&amp;gt;joinThreadPool();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个函数首先检查系统属性“debug.sf.nobootnimaition”的值是否不等于0。如果不等于的话，那么接下来就会启动一个Binder线程池，并且创建一个BootAnimation对象。这个BootAnimation对象就是用来显示第三个开机画面的。由于BootAnimation对象在显示第三个开机画面的过程中，需要与SurfaceFlinger服务通信，因此，应用程序bootanimation就需要启动一个Binder线程池。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接着我们看看BootAnimation类的声明，位于frameworks/base/cmds/bootanimation/BootAnimation.h中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; BootAnimation : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; Thread, &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; IBinder::DeathRecipient  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                BootAnimation();  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt;     ~BootAnimation();    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    .......  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;:  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt;        &lt;span class=&quot;title&quot;&gt;threadLoop&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; status_t    &lt;span class=&quot;title&quot;&gt;readyToRun&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;        &lt;span class=&quot;title&quot;&gt;onFirstRef&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;        &lt;span class=&quot;title&quot;&gt;binderDied&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; wp&amp;lt;IBinder&amp;gt;&amp;amp; who)&lt;/span&gt;&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; initTexture(Texture* texture, AssetManager&amp;amp; asset, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt;* name);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; initTexture(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Animation::Frame&amp;amp; frame);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;android&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;readFile&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt;* name, String8&amp;amp; outString)&lt;/span&gt;&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;movie&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;BootAnimation类继承了Thread类和IBinder::DeathRecipient类，其中几个重要的函数说明如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;onFirstRef()&lt;/strong&gt; —– 属于其父类RefBase，该函数在强引用sp新增引用计数時调用，就是当有sp包装的类初始化的时候调用；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;binderDied()&lt;/strong&gt; —– 当对象死掉或者其他情况导致该Binder结束时，就会回调binderDied()方法;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;readyToRun()&lt;/strong&gt; —– Thread执行前的初始化工作；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;threadLoop()&lt;/strong&gt; —– 每个线程类都要实现的，在这里定义thread的执行内容。这个函数如果返回true，且没有requestExist()没有被调用，则该函数会再次执行；如果返回false，则threadloop中的内容仅仅执行一次，线程就会退出。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;其他主要函数的说明如下：&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;android()&lt;/strong&gt; —– 显示系统默认的开机画面；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;movie()&lt;/strong&gt; —– 显示用户自定义的开机动画。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;BootAnimation类成员函数的实现位于frameworks/base/cmds/bootanimation/BootAnimation.cpp。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;BootAnimation类间接地继承了RefBase类，并且重写了RefBase类的成员函数onFirstRef，因此，当一个BootAnimation对象第一次被智能指针引用的时，这个BootAnimation对象的成员函数onFirstRef就会被调用：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; BootAnimation::onFirstRef() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = mSession-&amp;gt;linkToComposerDeath(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGE_IF(err, &lt;span class=&quot;string&quot;&gt;&quot;linkToComposerDeath failed (%s) &quot;&lt;/span&gt;, strerror(-err));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == NO_ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        run(&lt;span class=&quot;string&quot;&gt;&quot;BootAnimation&quot;&lt;/span&gt;, PRIORITY_DISPLAY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;mSession是BootAnimation类的一个成员变量，它的类型为SurfaceComposerClient，是用来和SurfaceFlinger执行Binder进程间通信的，它是在BootAnimation类的构造函数中创建的，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;BootAnimation::BootAnimation() : Thread(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;), mZip(&lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSession = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; SurfaceComposerClient();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceComposerClient类内部有一个实现了ISurfaceComposerClient接口的Binder代理对象mClient，这个Binder代理对象引用了SurfaceFlinger服务，SurfaceComposerClient类就是通过它来和SurfaceFlinger服务通信的。这个我们后面章节会详细分析。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;回到BootAnimation类的成员函数onFirstRef中，由于BootAnimation类引用了SurfaceFlinger服务，因此，当SurfaceFlinger服务意外死亡时，BootAnimation类就需要得到通知，这是通过调用成员变量mSession的成员函数linkToComposerDeath来注册SurfaceFlinger服务的死亡接收通知来实现的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;BootAnimation类继承了Thread类，因此，当BootAnimation类的成员函数onFirstRef调用了父类Thread的成员函数run之后，系统就会创建一个线程，这个线程在第一次运行之前，会调用BootAnimation类的成员函数readyToRun来执行一些初始化工作，后面再调用BootAnimation类的成员函数htreadLoop来显示第三个开机画面。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;BootAnimation类的成员函数readyToRun的实现如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; BootAnimation::readyToRun() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mAssets.addDefaultAssets();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//检查显示屏信息是否正确&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;IBinder&amp;gt; dtoken(SurfaceComposerClient::getBuiltInDisplay(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ISurfaceComposer::eDisplayIdMain));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    DisplayInfo dinfo;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; status = SurfaceComposerClient::getDisplayInfo(dtoken, &amp;amp;dinfo);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (status)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// create the native surface&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//调用SurfaceComposerClient对象mSession的成员函数createSurface可以获得一个SurfaceControl对象control&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;SurfaceControl&amp;gt; control = session()-&amp;gt;createSurface(String8(&lt;span class=&quot;string&quot;&gt;&quot;BootAnimation&quot;&lt;/span&gt;),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    SurfaceComposerClient::openGlobalTransaction();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    control-&amp;gt;setLayer(&lt;span class=&quot;number&quot;&gt;0x40000000&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    SurfaceComposerClient::closeGlobalTransaction();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//调用SurfaceControl对象control的成员函数getSurface会返回一个Surface对象s&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;Surface&amp;gt; s = control-&amp;gt;getSurface();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// initialize opengl and egl&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//初始化OPENEGL和EGL&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; EGLint attribs[] = &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            EGL_RED_SIZE,   &lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            EGL_GREEN_SIZE, &lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            EGL_BLUE_SIZE,  &lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            EGL_DEPTH_SIZE, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            EGL_NONE&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLint w, h, dummy;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLint numConfigs;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLConfig config;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLSurface surface;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLContext context;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    eglInitialize(display, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    eglChooseConfig(display, attribs, &amp;amp;config, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &amp;amp;numConfigs);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    surface = eglCreateWindowSurface(display, config, s.get(), &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    context = eglCreateContext(display, config, &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;, &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    eglQuerySurface(display, surface, EGL_WIDTH, &amp;amp;w);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    eglQuerySurface(display, surface, EGL_HEIGHT, &amp;amp;h);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_INIT;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mDisplay = display;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mContext = context;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSurface = surface;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mWidth = w;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mHeight = h;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFlingerSurfaceControl = control;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFlingerSurface = s;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// If the device has encryption turned on or is in process&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// of being encrypted we show the encrypted boot animation.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果设备加密功能开启了，就要显示加密的开机动画&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; decrypt[PROPERTY_VALUE_MAX];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    property_get(&lt;span class=&quot;string&quot;&gt;&quot;vold.decrypt&quot;&lt;/span&gt;, decrypt, &lt;span class=&quot;string&quot;&gt;&quot;&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; encryptedAnimation = atoi(decrypt) != &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; || !&lt;span class=&quot;built_in&quot;&gt;strcmp&lt;/span&gt;(&lt;span class=&quot;string&quot;&gt;&quot;trigger_restart_min_framework&quot;&lt;/span&gt;, decrypt);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//选取动画文件&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ZipFileRO* zipFile = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((encryptedAnimation &amp;amp;&amp;amp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;amp;&amp;amp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ((zipFile = ZipFileRO::open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE)) != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;)) ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ((access(OEM_BOOTANIMATION_FILE, R_OK) == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;amp;&amp;amp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ((zipFile = ZipFileRO::open(OEM_BOOTANIMATION_FILE)) != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;)) ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ((access(SYSTEM_BOOTANIMATION_FILE, R_OK) == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;amp;&amp;amp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ((zipFile = ZipFileRO::open(SYSTEM_BOOTANIMATION_FILE)) != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;))) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mZip = zipFile;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; NO_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;readyToRun主要做了如下工作：&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）BootAnimation类的成员函数session用来返回BootAnimation类的成员变量mSession所描述的一个SurfaceComposerClient对象。通过调用SurfaceComposerClient对象mSession的成员函数createSurface可以获得一个SurfaceControl对象control。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceComposerClient类的成员函数createSurface首先调用内部的Binder代理对象mClient(frameworks/native/services/surfaceflinger/Client.cpp)来请求SurfaceFlinger返回一个类型为(class Handle : public BBinder, public LayerCleaner)Binder代理对象（封装了SurfaceFlinger的sp指针和Layer对象）handle，和一个IGraphicBufferProducer的sp指针（封装了SurfaceFlinger的sp指针）gbp，接着再使用这两个对象来创建一个SurfaceControl对象。创建出来的SurfaceControl对象的成员变量handle就指向了从SurfaceFlinger返回来的类型为Handle 的Binder代理对象。有了这个Binder代理对象之后，SurfaceControl对象就可以和SurfaceFlinger服务通信了。(下一章节会分析)&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;调用SurfaceControl对象control的成员函数getSurface会返回一个Surface对象s。这个Surface对象s内部也有一个类型为IGraphicBufferProducer的sp指针mGraphicBufferProducer，这个sp指针与前面所创建的SurfaceControl对象control的内部的sp指针（封装了SurfaceFlinger的sp指针）gbp引用的是同一个对象。这样，Surface对象s也可以通过其内部的sp指针mGraphicBufferProducer来和SurfaceFlinger服务通信。（下一章节会分析）&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Surface类继承了ANativeWindow类。ANativeWindow类是连接OpenGL和Android窗口系统的桥梁，即OpenGL需要通过ANativeWindow类来间接地操作Android窗口系统。这种桥梁关系是通过EGL库来建立的，所有以egl为前缀的函数名均为EGL库提供的接口。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）为了能够在OpenGL和Android窗口系统之间的建立一个桥梁，我们需要一个EGLDisplay对象display，一个EGLConfig对象config，一个EGLSurface对象surface，以及一个EGLContext对象context，其中，EGLDisplay对象display用来描述一个EGL显示屏，EGLConfig对象config用来描述一个EGL帧缓冲区配置参数，EGLSurface对象surface用来描述一个EGL绘图表面，EGLContext对象context用来描述一个EGL绘图上下文（状态），它们是分别通过调用egl库函数eglGetDisplay、eglChooseConfig、eglCreateWindowSurface和eglCreateContext来获得的。注意，EGLConfig对象config、EGLSurface对象surface和EGLContext对象context都是用来描述EGLDisplay对象display的。有了这些对象之后，就可以调用函数eglMakeCurrent来设置当前EGL库所使用的绘图表面以及绘图上下文。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;还有另外一个地方需要注意的是，每一个EGLSurface对象surface有一个关联的ANativeWindow对象。这个ANativeWindow对象是通过函数eglCreateWindowSurface的第三个参数来指定的。在我们这个场景中，这个ANativeWindow对象正好对应于前面所创建的 Surface对象s。每当OpenGL需要绘图的时候，它就会找到前面所设置的绘图表面，即EGLSurface对象surface。有了EGLSurface对象surface之后，就可以找到与它关联的ANativeWindow对象，即Surface对象s。有了Surface对象s之后，就可以通过其内部的sp指针mGraphicBufferProducer来请求SurfaceFlinger服务返回帧缓冲区硬件设备的一个图形访问接口。这样，OpenGL最终就可以将要绘制的图形渲染到帧缓冲区硬件设备中去，即显示在实际屏幕上。屏幕的大小，即宽度和高度，可以通过函数eglQuerySurface来获得。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）动画文件的读取是按顺序进行的，如果读取成功，则不再读取后续的文件，如果失败，则读取下一个文件。顺序如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;如果设备的加密功能已经开启，或者设备正在进行加密，则读取加密开机动画文件，路径为：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;define&lt;/span&gt; SYSTEM_ENCRYPTED_BOOTANIMATION_FILE &lt;span class=&quot;string&quot;&gt;&quot;/system/media/bootanimation-encrypted.zip&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OEM厂商指定的开机动画，路径为：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;define&lt;/span&gt; OEM_BOOTANIMATION_FILE &lt;span class=&quot;string&quot;&gt;&quot;/oem/media/bootanimation.zip&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;系统开机动画，路径为：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;define&lt;/span&gt; SYSTEM_BOOTANIMATION_FILE &lt;span class=&quot;string&quot;&gt;&quot;/system/media/bootanimation.zip&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这一步执行完成之后，用来显示第三个开机画面的线程的初始化工作就执行完成了，接下来，就会执行这个线程的主体函数，即BootAnimation类的成员函数threadLoop。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;BootAnimation类的成员函数threadLoop的实现如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; BootAnimation::threadLoop()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; r;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// We have no bootanimation file, so we use the stock android logo&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// animation.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mZip == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        r = android();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        r = movie();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    eglDestroyContext(mDisplay, mContext);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    eglDestroySurface(mDisplay, mSurface);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFlingerSurface.clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFlingerSurfaceControl.clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    eglTerminate(mDisplay);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    IPCThreadState::self()-&amp;gt;stopProcess();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; r;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个函数流程比较简单，首先判断自定义的开机动画文件mZip是否存在，如果存在就调用movie()完成自定义开机画面的显示；如果不存在，调用android()完成系统默认开机画面的显示。然后进行开机动画显示后的销毁、释放工作，主要就是readyToRun中初始化的一些EGL对象。最后终止线程，并return。注意，movie()和android()的返回值都是false，因此线程结束也会返回false。threadLoop()函数如果返回值为false，则该函数中的内容只会执行一次；如果返回true，则会不停的执行。这里返回false，因此只会执行一次。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接下来，我们就分别分析BootAnimation类的成员函数android和movie的实现。&lt;/p&gt;
&lt;h3 id=&quot;系统默认开机动画android&quot;&gt;&lt;a href=&quot;#系统默认开机动画android&quot; class=&quot;headerlink&quot; title=&quot;系统默认开机动画android()&quot;&gt;&lt;/a&gt;系统默认开机动画android()&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;BootAnimation类的成员函数android的实现如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; BootAnimation::android()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//读取开机动画默认图片，根据图片创建两个纹理对象&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//&quot;android&quot;字样图片&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    initTexture(&amp;amp;mAndroid[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;], mAssets, &lt;span class=&quot;string&quot;&gt;&quot;images/android-logo-mask.png&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//闪光图片&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    initTexture(&amp;amp;mAndroid[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;], mAssets, &lt;span class=&quot;string&quot;&gt;&quot;images/android-logo-shine.png&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// clear screen&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//清理屏幕&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glShadeModel(GL_FLAT);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glDisable(GL_DITHER);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glDisable(GL_SCISSOR_TEST);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glClearColor(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glClear(GL_COLOR_BUFFER_BIT);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    eglSwapBuffers(mDisplay, mSurface);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glEnable(GL_TEXTURE_2D);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//图片在屏幕中现实位置&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; GLint xc = (mWidth  - mAndroid[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].w) / &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; GLint yc = (mHeight - mAndroid[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].h) / &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Rect &lt;span class=&quot;title&quot;&gt;updateRect&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(xc, yc, xc + mAndroid[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].w, yc + mAndroid[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].h)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            updateRect.height());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Blend state&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; startTime = systemTime();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;do&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//计算每次偏移时间，然后计算出偏移位置&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; now = systemTime();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;double&lt;/span&gt; time = now - startTime;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;float&lt;/span&gt; t = &lt;span class=&quot;number&quot;&gt;4.0f&lt;/span&gt; * &lt;span class=&quot;keyword&quot;&gt;float&lt;/span&gt;(time / us2ns(&lt;span class=&quot;number&quot;&gt;16667&lt;/span&gt;)) / mAndroid[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;].w;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        GLint offset = (&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt; - (t - floorf(t))) * mAndroid[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;].w;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        GLint x = xc - offset;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        glDisable(GL_SCISSOR_TEST);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        glClear(GL_COLOR_BUFFER_BIT);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        glEnable(GL_SCISSOR_TEST);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        glDisable(GL_BLEND);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//绘制闪光图片，这个会根据上面计算的位置来显示&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        glBindTexture(GL_TEXTURE_2D, mAndroid[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;].name);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        glDrawTexiOES(x,                 yc, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, mAndroid[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;].w, mAndroid[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;].h);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        glDrawTexiOES(x + mAndroid[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;].w, yc, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, mAndroid[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;].w, mAndroid[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;].h);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        glEnable(GL_BLEND);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//绘制Android字样的图片，这个不动&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        glBindTexture(GL_TEXTURE_2D, mAndroid[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].name);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        glDrawTexiOES(xc, yc, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, mAndroid[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].w, mAndroid[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].h);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//交换缓冲区，以显示到屏幕&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        EGLBoolean res = eglSwapBuffers(mDisplay, mSurface);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (res == EGL_FALSE)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// 12fps: don&#39;t animate too fast to preserve CPU&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; sleepTime = &lt;span class=&quot;number&quot;&gt;83333&lt;/span&gt; - ns2us(systemTime() - now);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (sleepTime &amp;gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            usleep(sleepTime);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//最后执行checkExit函数，判断是否退出了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        checkExit();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (!exitPending());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glDeleteTextures(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &amp;amp;mAndroid[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].name);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glDeleteTextures(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &amp;amp;mAndroid[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;].name);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;一共有以下几个步骤：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1） Android系统默认的开机动画是由两张图片android-logo-mask.png和android-logo-shine.png中。这两张图片保存在frameworks/base/core/res/assets/images目录中，它们最终会被编译在framework-res模块（frameworks/base/core/res）中，即编译在framework-res.apk文件中。编译在framework-res模块中的资源文件可以通过AssetManager类来访问。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%B8%89%29----Android%E5%BC%80%E6%9C%BA%E5%8A%A8%E7%94%BB%E6%B5%81%E7%A8%8B%E7%AE%80%E8%BF%B0/img.jpg&quot; alt=&quot;开机两张图片&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;BootAnimation类的成员函数android首先调用另外一个成员函数initTexture来将根据图片android-logo-mask.png和android-logo-shine.png的内容来分别创建两个纹理对象，这两个纹理对象就分别保存在BootAnimation类的成员变量mAndroid所描述的一个数组中。通过混合渲染这两个纹理对象，我们就可以得到一个开机动画，这是通过中间的while循环语句来实现的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）图片android-logo-mask.png用作动画前景，它是一个镂空的“ANDROID”图像。图片android-logo-shine.png用作动画背景，它的中间包含有一个高亮的呈45度角的条纹。在每一次循环中，图片android-logo-shine.png被划分成左右两部分内容来显示。左右两个部分的图像宽度随着时间的推移而此消彼长，这样就可以使得图片android-logo-shine.png中间高亮的条纹好像在移动一样。另一方面，在每一次循环中，图片android-logo-mask.png都作为一个整体来渲染，而且它的位置是恒定不变的。由于它是一个镂空的“ANDROID”图像，因此，我们就可以通过它的镂空来看到它背后的图片android-logo-shine.png的条纹一闪一闪地划过。这个while循环语句会一直被执行，直到应用程序/system/bin/bootanimation被结束为止。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）在循环语句最后会执行checkExit()函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; BootAnimation::checkExit() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Allow surface flinger to gracefully request shutdown&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; value[PROPERTY_VALUE_MAX];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    property_get(EXIT_PROP_NAME, value, &lt;span class=&quot;string&quot;&gt;&quot;0&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; exitnow = atoi(value);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (exitnow) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        requestExit();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mAudioPlayer != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mAudioPlayer-&amp;gt;requestExit();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;首先调用property_get获取属性EXIT_PROP_NAME的值:&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;define&lt;/span&gt; EXIT_PROP_NAME &lt;span class=&quot;string&quot;&gt;&quot;service.bootanim.exit&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后判断该值，如果为1，则调用requestExit（）要求退出当前线程，该函数是异步的。位于system/core/libutils/Thread.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; Thread::requestExit()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::Autolock _l(mLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//这里将mExitPending 赋值为true&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mExitPending = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;回到android()代码：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125; &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (!exitPending());&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;调用exitPending()，改函数判断requestExit（）是否被调用过，如果调用过则返回true，否则为false。依然位于system/core/libutils/Thread.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; Thread::exitPending() &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::Autolock _l(mLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//上面我们在requestExit赋过值了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mExitPending;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这样，当属性“service.bootanim.exit”值被设为”1”时，android()就会调用requestExit()，exitPending()返回值为true。于是do…while()循环就会退出，开机动画绘制就会结束。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;至于什么时候是哪个服务将属性“service.bootanim.exit”的值设置为1的，我们后面讲开机动画的停止的时候会提到。&lt;/p&gt;
&lt;h3 id=&quot;自定义开机动画movie&quot;&gt;&lt;a href=&quot;#自定义开机动画movie&quot; class=&quot;headerlink&quot; title=&quot;自定义开机动画movie()&quot;&gt;&lt;/a&gt;自定义开机动画movie()&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;BootAnimation类的成员函数movie的实现比较长，我们分段来阅读：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Part.1：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; BootAnimation::movie()&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;String8 desString;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//读取desc.txt文件内容&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!readFile(&lt;span class=&quot;string&quot;&gt;&quot;desc.txt&quot;&lt;/span&gt;, desString)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* s = desString.&lt;span class=&quot;built_in&quot;&gt;string&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Create and initialize an AudioPlayer if we have an audio_conf.txt file&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果存在audio_conf.txt文件，则会创建一个AudioPlayer，并根据读取的字符串初始化&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//ignore it&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    String8 audioConf;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (readFile(&lt;span class=&quot;string&quot;&gt;&quot;audio_conf.txt&quot;&lt;/span&gt;, audioConf)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mAudioPlayer = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; AudioPlayer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mAudioPlayer-&amp;gt;init(audioConf.&lt;span class=&quot;built_in&quot;&gt;string&lt;/span&gt;())) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;mAudioPlayer.init failed&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mAudioPlayer = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从前面BootAnimation类的成员函数readyToRun的实现可以知道，如果目标设备上存在压缩文件/system/media/bootanimation.zip(另外两种我们忽略)，那么BootAnimation类的成员变量mZip就会指向它，这段代码作用是读取开机动画文件mZip中的描述文件“desc.txt”。每个动画文件压缩包中必须要包含一个desc.txt，该文件用来描述开机动画如何显示。下面以一个示例来分析一下该文件：&lt;br&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;number&quot;&gt;480&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;640&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;20&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;p &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; folder1  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;p &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;20&lt;/span&gt; folder2  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;c &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; folder3  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;c &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; folder4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Part.2：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;第1行用来描述开机动画在屏幕显示的大小及速度。具体为：开机动画的宽度为480个像素，高度为640个像素，显示频率为每秒20帧，即每帧显示1/20秒。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;下面的每一行代表一个片段，显示的时候会按照顺序从上到下依次显示。第1个字符为片段类型，有’c’和’p’两种，两者的区别后面会结合代码说明。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;第2个数字为该片段重复显示的次数，如果为‘0’，表示会无限重复显示；第3个数字为两次显示之间的间隔，单位为第一行中定义的每帧显示的时间；第4个字符串为该片段所在的文件夹，一个片段可以由多个png图片组成，都存放在folder文件夹中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;“p 1 0 folder1”代表该片段显示1次，与下一个片段间隔0s，该片段的显示图片路径为bootanimation.zip/folder1。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;“p 2 20 folder2”代表该片段显示2次，且两次之间显示的间隔为20&lt;em&gt;(1/20)=1s，与下一个片段间隔20&lt;/em&gt;(1/20)=1s，该片段的显示图片路径为bootanimation.zip/folder2。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;“c 0 0 folder3”代表该片段无限循环显示，且两次显示的间隔为0s，与下一个片段间隔0s，该片段的显示图路径为bootanimation.zip/folder3。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;“c 1 10 folder4”代表该片段显示1次，显示后暂停10*(1/20)=0.5s，该片段的显示图路径为bootanimation.zip/folder4。&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; BootAnimation::movie()&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.1&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Animation animation;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// Parse the description file&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (;;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt;* &lt;span class=&quot;built_in&quot;&gt;endl&lt;/span&gt; = &lt;span class=&quot;built_in&quot;&gt;strstr&lt;/span&gt;(s, &lt;span class=&quot;string&quot;&gt;&quot;\n&quot;&lt;/span&gt;);&lt;span class=&quot;comment&quot;&gt;//检测首次出现换行符的地址&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!&lt;span class=&quot;built_in&quot;&gt;endl&lt;/span&gt;) &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//每次读取一行&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;function&quot;&gt;String8 &lt;span class=&quot;title&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(s, &lt;span class=&quot;built_in&quot;&gt;endl&lt;/span&gt; - s)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt;* l = line.&lt;span class=&quot;built_in&quot;&gt;string&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; fps, width, height, count, pause;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; path[ANIM_ENTRY_NAME_MAX];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; color[&lt;span class=&quot;number&quot;&gt;7&lt;/span&gt;] = &lt;span class=&quot;string&quot;&gt;&quot;000000&quot;&lt;/span&gt;; &lt;span class=&quot;comment&quot;&gt;// default to black if unspecified&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; pathType;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;built_in&quot;&gt;sscanf&lt;/span&gt;(l, &lt;span class=&quot;string&quot;&gt;&quot;%d %d %d&quot;&lt;/span&gt;, &amp;amp;width, &amp;amp;height, &amp;amp;fps) == &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//每行如果有三个字符串，则依次是宽、高、帧率&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// ALOGD(&quot;&amp;gt; w=%d, h=%d, fps=%d&quot;, width, height, fps);&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            animation.width = width;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            animation.height = height;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            animation.fps = fps;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果是大于等于四个字符串，则依次是显示类型、显示次数、与下一次间隔时间、显示颜色&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;built_in&quot;&gt;sscanf&lt;/span&gt;(l, &lt;span class=&quot;string&quot;&gt;&quot; %c %d %d %s #%6s&quot;&lt;/span&gt;, &amp;amp;pathType, &amp;amp;count, &amp;amp;pause, path, color) &amp;gt;= &lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// ALOGD(&quot;&amp;gt; type=%c, count=%d, pause=%d, path=%s, color=%s&quot;, pathType, count, pause, path, color);&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Animation::Part part;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            part.playUntilComplete = pathType == &lt;span class=&quot;string&quot;&gt;&#39;c&#39;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            part.count = count;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            part.pause = pause;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            part.path = path;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            part.audioFile = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!parseColor(color, part.backgroundColor)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;&amp;gt; invalid color &#39;#%s&#39;&quot;&lt;/span&gt;, color);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                part.backgroundColor[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;] = &lt;span class=&quot;number&quot;&gt;0.0f&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                part.backgroundColor[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;] = &lt;span class=&quot;number&quot;&gt;0.0f&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                part.backgroundColor[&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;] = &lt;span class=&quot;number&quot;&gt;0.0f&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            animation.parts.add(part);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        s = ++&lt;span class=&quot;built_in&quot;&gt;endl&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面的for循环语句分析完成desc.txt文件的内容后，就得到了开机动画的显示大小、速度以及片断信息。这些信息都保存在Animation对象animation中，其中，每一个动画片断都使用一个Animation::Part对象来描述，并且保存在Animation对象animation的成员变量parts所描述的一个片断列表中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Part.3：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;bool BootAnimation::movie()&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part.1...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part.2...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // read all the data structures&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //开始读取zip文件&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const size_t pcount = animation.parts.size();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    void *cookie = NULL;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    if (!mZip-&amp;gt;startIteration(&amp;amp;cookie)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        return false;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ZipEntryRO entry;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    char name[ANIM_ENTRY_NAME_MAX];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //开始循环遍历每一个文件&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    while ((entry = mZip-&amp;gt;nextEntry(cookie)) != NULL) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const int foundEntryName = mZip-&amp;gt;getEntryFileName(entry, name, ANIM_ENTRY_NAME_MAX);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (foundEntryName &amp;gt; ANIM_ENTRY_NAME_MAX || foundEntryName == -1) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ALOGE(&quot;Error fetching entry file name&quot;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            continue;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const String8 entryName(name);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const String8 path(entryName.getPathDir());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const String8 leaf(entryName.getPathLeaf());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (leaf.size() &amp;gt; 0) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            for (size_t j=0 ; j&amp;lt;pcount ; j++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                if (path == animation.parts[j].path) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    int method;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    // supports only stored png files&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    if (mZip-&amp;gt;getEntryInfo(entry, &amp;amp;method, NULL, NULL, NULL, NULL, NULL)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        if (method == ZipFileRO::kCompressStored) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            FileMap* map = mZip-&amp;gt;createEntryFileMap(entry);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            if (map) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                Animation::Part&amp;amp; part(animation.parts.editItemAt(j));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                if (leaf == &quot;audio.wav&quot;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                    // a part may have at most one audio file&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                    part.audioFile = map;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                &amp;#125; else &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                    Animation::Frame frame;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                    frame.name = leaf;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                    frame.map = map;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                    part.frames.add(frame);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mZip-&amp;gt;endIteration(cookie);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接下来，BootAnimation类的成员函数movie再断续将每一个片断所对应的png图片读取出来。每一个png图片都表示一个动画帧，使用一个Animation::Frame对象来描述，并且保存在对应的Animation::Part对象的成员变量frames所描述的一个帧列表中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Part.4：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;bool BootAnimation::movie()&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part.1...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part.2...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part.3...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // clear screen&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glShadeModel(GL_FLAT);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glDisable(GL_DITHER);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glDisable(GL_SCISSOR_TEST);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glDisable(GL_BLEND);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glClearColor(0,0,0,1);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glClear(GL_COLOR_BUFFER_BIT);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    eglSwapBuffers(mDisplay, mSurface);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glBindTexture(GL_TEXTURE_2D, 0);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glEnable(GL_TEXTURE_2D);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const int xc = (mWidth - animation.width) / 2;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const int yc = ((mHeight - animation.height) / 2);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    nsecs_t lastFrame = systemTime();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    nsecs_t frameDuration = s2ns(1) / animation.fps;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Region clearReg(Rect(mWidth, mHeight));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    clearReg.subtractSelf(Rect(xc, yc, xc+animation.width, yc+animation.height));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;前面的一系列gl函数首先用来清理屏幕，接下来的一系列gl函数用来设置OpenGL的纹理显示方式。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;变量xc和yc的值用来描述开机动画的显示位置，即需要在屏幕中间显示开机动画，另外一个变量frameDuration的值用来描述每一帧的显示时间，它是以纳秒为单位的。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Region对象clearReg用来描述屏幕中除了开机动画之外的其它区域，它是用整个屏幕区域减去开机动画所点据的区域来得到的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Part.5：&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;96&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;97&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;98&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;99&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;100&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;101&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;102&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;103&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;104&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;105&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;bool BootAnimation::movie()&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part.1...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part.2...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part.3...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part.4...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //第一层for循环用来显示每一个动画片断&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    for (size_t i=0 ; i&amp;lt;pcount ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const Animation::Part&amp;amp; part(animation.parts[i]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        const size_t fcount = part.frames.size();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        glBindTexture(GL_TEXTURE_2D, 0);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //第二层的for循环用来循环显示每一个动画片断&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        for (int r=0 ; !part.count || r&amp;lt;part.count ; r++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // Exit any non playuntil complete parts immediately&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if(exitPending() &amp;amp;&amp;amp; !part.playUntilComplete)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                break;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // only play audio file the first time we animate the part&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if (r == 0 &amp;amp;&amp;amp; mAudioPlayer != NULL &amp;amp;&amp;amp; part.audioFile) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mAudioPlayer-&amp;gt;playFile(part.audioFile);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            glClearColor(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    part.backgroundColor[0],&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    part.backgroundColor[1],&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    part.backgroundColor[2],&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    1.0f);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //第三层的for循环用来显示每一个动画片断所对应的png图片&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //可以看到，如果exitPending()返回值为true且part.playUntilComplete=false，则会break。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //即：当SurfaceFlinger服务要求bootanimation停止显示动画时，以‘p’标识的片段会停止，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //而以&#39;c&#39;标识的片段会继续显示。这就是两者之间的主要区别。 &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            for (size_t j=0 ; j&amp;lt;fcount &amp;amp;&amp;amp; (!exitPending() || part.playUntilComplete) ; j++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                const Animation::Frame&amp;amp; frame(part.frames[j]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                nsecs_t lastFrame = systemTime();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                if (r &amp;gt; 0) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    glBindTexture(GL_TEXTURE_2D, frame.tid);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125; else &amp;#123;//如果一个动画片断的循环显示次数不等于1，那么就说明这个动画片断中的png图片需要重复地显示在屏幕中&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    //第一次显示一个png图片的时候，会调用函数glGenTextures来为这个png图片创建一个纹理对象,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    //并且将这个纹理对象的名称保存在对应的Animation::Frame对象的成员变量tid中&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    if (part.count != 1) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        glGenTextures(1, &amp;amp;frame.tid);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        glBindTexture(GL_TEXTURE_2D, frame.tid);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    initTexture(frame);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                // 如果Region对象clearReg所包含的区域不为空,首先要将它所包含的区域裁剪掉，避免开机动画可以显示在指定的位置以及大小中&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                if (!clearReg.isEmpty()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    Region::const_iterator head(clearReg.begin());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    Region::const_iterator tail(clearReg.end());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    glEnable(GL_SCISSOR_TEST);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    while (head != tail) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        const Rect&amp;amp; r(*head++);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        glScissor(r.left, mHeight - r.bottom,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                r.width(), r.height());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        glClear(GL_COLOR_BUFFER_BIT);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    glDisable(GL_SCISSOR_TEST);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                glDrawTexiOES(xc, yc, 0, animation.width, animation.height);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                eglSwapBuffers(mDisplay, mSurface);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                nsecs_t now = systemTime();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                nsecs_t delay = frameDuration - (now - lastFrame);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //ALOGD(&quot;%lld, %lld&quot;, ns2ms(now - lastFrame), ns2ms(delay));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                lastFrame = now;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                //调用函数usleep函数来让线程睡眠一下，以保证每一个png图片，即每一帧动画都按照预先指定好的速度来显示&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                if (delay &amp;gt; 0) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    struct timespec spec;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    spec.tv_sec  = (now + delay) / 1000000000;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    spec.tv_nsec = (now + delay) % 1000000000;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    int err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    do &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &amp;amp;spec, NULL);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125; while (err&amp;lt;0 &amp;amp;&amp;amp; errno == EINTR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                checkExit();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //每当循环显示完成一个片断时，需要调用usleep函数来使得线程睡眠part.pause * ns2us(frameDuration)毫秒，以便可以按照预先设定的节奏来显示开机动画。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            usleep(part.pause * ns2us(frameDuration));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            // For infinite parts, we&#39;ve now played them at least once, so perhaps exit&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            //如果无限循环，则检查是否有退出消息来了，上面android()函数分析过了&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            if(exitPending() &amp;amp;&amp;amp; !part.count)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                break;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        // free the textures for this part&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //最后一个if语句判断一个动画片断是否是循环显示的，即循环次数不等于1。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //如果是的话，那么就说明前面为它所对应的每一个png图片都创建过一个纹理对象。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        //现在既然这个片断的显示过程已经结束了，因此，就需要释放前面为它所创建的纹理对象。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        if (part.count != 1) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            for (size_t j=0 ; j&amp;lt;fcount ; j++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                const Animation::Frame&amp;amp; frame(part.frames[j]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                glDeleteTextures(1, &amp;amp;frame.tid);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    return false;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）第一层for循环用来显示每一个动画片断，第二层的for循环用来循环显示每一个动画片断，第三层的for循环用来显示每一个动画片断所对应的png图片。这些png图片以纹理的方式来显示在屏幕中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）注意，如果一个动画片断的循环显示次数不等于1，那么就说明这个动画片断中的png图片需要重复地显示在屏幕中。由于每一个png图片都需要转换为一个纹理对象之后才能显示在屏幕中，因此，为了避免重复地为同一个png图片创建纹理对象，第三层的for循环在第一次显示一个png图片的时候，会调用函数glGenTextures来为这个png图片创建一个纹理对象，并且将这个纹理对象的名称保存在对应的Animation::Frame对象的成员变量tid中，这样，下次再显示相同的图片时，就可以使用前面已经创建好了的纹理对象，即调用函数glBindTexture来指定当前要操作的纹理对象。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）如果Region对象clearReg所包含的区域不为空，那么在调用函数glDrawTexiOES和eglSwapBuffers来显示每一个png图片之前，首先要将它所包含的区域裁剪掉，避免开机动画可以显示在指定的位置以及大小中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4） 每当显示完成一个png图片之后，都要将变量frameDuration的值从纳秒转换为毫秒。如果转换后的值大小于，那么就需要调用函数usleep函数来让线程睡眠一下，以保证每一个png图片，即每一帧动画都按照预先指定好的速度来显示。注意，函数usleep指定的睡眠时间只能精确到毫秒，因此，如果预先指定的帧显示时间小于1毫秒，那么BootAnimation类的成员函数movie是无法精确地控制地每一帧的显示时间的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;5）还有另外一个地方需要注意的是，每当循环显示完成一个片断时，需要调用usleep函数来使得线程睡眠part.pause * ns2us(frameDuration)毫秒，以便可以按照预先设定的节奏来显示开机动画。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;6）最后一个if语句判断一个动画片断是否是循环显示的，即循环次数不等于1。如果是的话，那么就说明前面为它所对应的每一个png图片都创建过一个纹理对象。现在既然这个片断的显示过程已经结束了，因此，就需要释放前面为它所创建的纹理对象。&lt;/p&gt;
&lt;p&gt;附注：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;可以看到，如果exitPending()返回值为true且part.playUntilComplete=false，则会break。即：当SurfaceFlinger服务要求bootanimation停止显示动画时，以‘p’标识的片段会停止，而以’c’标识的片段会继续显示。这就是两者之间的主要区别。 我猜想”c”标识的意思是continue，即：即使SurfaceFlinger要求bootanimation停止动画，bootanimation也不会立刻停止动画，它会等c标识片段都显示完毕后，再停止。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;至此，第三个开机画面的显示过程就分析完成了。&lt;/p&gt;
&lt;h2 id=&quot;开机动画的停止&quot;&gt;&lt;a href=&quot;#开机动画的停止&quot; class=&quot;headerlink&quot; title=&quot;开机动画的停止&quot;&gt;&lt;/a&gt;开机动画的停止&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接下来，我们再继续分析第三个开机画面是如何停止显示的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当System进程将系统中的关键服务启动起来之后，就会将Launcher启动起来。Android应用程序的启动过程实际上就是它的根Activity组件的启动过程。对于应用程序Launcher来说，它的根Activity组件即为Launcher组件。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;一个Activity组件在启动起来之后，就会被记录起来，等到它所运行在的主线程空闲的时候，这个主线程就会向ActivityManagerService发送一个Activity组件空闲的通知。由于应用程序Launcher是系统中第一个被启动的应用程序，即它的根Activity组件是系统中第一个被启动的Activity组件，因此，当ActivityManagerService接收到它的空闲通知的时候，就可以知道系统是刚刚启动起来的。在这种情况下，ActivityManagerService就会停止显示开机动画，以便可以在屏幕中显示应用程序Lancher的界面。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果一个线程想要在空闲的时候处理一些事务，那么就必须要向这个线程的消息队列注册一个空闲消息处理器。自定义的空闲消息处理器灯必须要从MessageQueue.IdleHandler类继承下来，并且重写成员函数queueIdle。当一个线程空闲的时候，即消息队列中没有新的消息需要处理的时候，那些注册了的空闲消息处理器的成员函数queueIdle就会被调用。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;应用程序的主线程是通过ActivityThread类来描述的，它实现在文件frameworks/base/core/Java/android/app/ActivityThread.java中。每当有一个新的Activity组件启动起来的时候，ActivityThread类都会向它所描述的应用程序主线程的消息队列注册一个类型为Idler的空闲消息处理器。这样一个应用程序的主线程就可以在空闲的时候，向ActivityManagerService发送一个Activity组件空闲通知，相当于是通知ActivityManagerService，一个新的Activity组件已经准备就绪了。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Idler类定义在frameworks/base/core/java/android/app/ActivityThread.java中， 它的成员函数queueIdle的实现如下所示：&lt;br&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Idler&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;MessageQueue&lt;/span&gt;.&lt;span class=&quot;title&quot;&gt;IdleHandler&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;meta&quot;&gt;@Override&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;queueIdle&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ActivityClientRecord a = mNewActivities;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (a != &lt;span class=&quot;keyword&quot;&gt;null&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mNewActivities = &lt;span class=&quot;keyword&quot;&gt;null&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            IActivityManager am = ActivityManagerNative.getDefault();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ActivityClientRecord prev;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            do &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                .....&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (a.activity != &lt;span class=&quot;keyword&quot;&gt;null&lt;/span&gt; &amp;amp;&amp;amp; !a.activity.mFinished) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;try&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        am.activityIdle(a.token, a.createdConfig, stopProfiling);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        a.createdConfig = &lt;span class=&quot;keyword&quot;&gt;null&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;catch&lt;/span&gt; (RemoteException ex) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// Ignore&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                prev = a;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                a = a.nextIdle;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                prev.nextIdle = &lt;span class=&quot;keyword&quot;&gt;null&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (a != &lt;span class=&quot;keyword&quot;&gt;null&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;ActivityThread类有一个类型为ActivityClientRecord的成员变量mNewActivities，用来描述所有在当前应用程序主线程中新启动起来的Activity组件。这些新启动起来的Activity组件通过ActivityClientRecord类的成员变量nextIdle连接在一起。一旦当前应用程序主线程向ActivityManagerService发送了这些新启动的Activity组件的空闲通知之后，这些新启动起来的Activity组件就不会再被保存在ActivityThread类的成员变量mNewActivities中了，即每一个新启动的Activity组件只有一次机会向ActivityManagerService发送一个空闲通知。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;向ActivityManagerService发送一个Activity组件空闲通知是通过调用ActivityManagerService代理对象的成员函数activityIdle来实现的，而ActivityManagerService代理对象可以通过调用ActivityManagerNative类的静态成员函数getDefault来获得。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;ActivityManagerService代理对象的类型为ActivityManagerProxy，它的成员函数activityIdle实现在文件frameworks/base/core/java/android/app/ActivityManagerNative.java中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;ActivityManagerProxy&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;IActivityManager&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;activityIdle&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(IBinder token, Configuration config)&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;throws&lt;/span&gt; RemoteException  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Parcel data = Parcel.obtain();  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Parcel reply = Parcel.obtain();  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        data.writeInterfaceToken(IActivityManager.descriptor);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        data.writeStrongBinder(token);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (config != &lt;span class=&quot;keyword&quot;&gt;null&lt;/span&gt;) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            data.writeInt(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            config.writeToParcel(data, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            data.writeInt(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mRemote.transact(ACTIVITY_IDLE_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        reply.readException();  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        data.recycle();  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        reply.recycle();  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;ActivityManagerProxy类的成员函数activityIdle实际上是向ActivityManagerService发送一个类型为ACTIVITY_IDLE_TRANSACTION的Binder进程间通信请求，其中，参数token用来描述与这个进程间通信请求所关联的一个Activity组件，在我们这个场景中，这个Activity组件即为应用程序Launcher的根Activity组件Launcher。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;类型为ACTIVITY_IDLE_TRANSACTION的Binder进程间通信请求是由ActivityManagerService类的成员函数activityIdle来处理的，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;ActivityManagerService&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;ActivityManagerNative&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Watchdog&lt;/span&gt;.&lt;span class=&quot;title&quot;&gt;Monitor&lt;/span&gt;, &lt;span class=&quot;title&quot;&gt;BatteryStatsImpl&lt;/span&gt;.&lt;span class=&quot;title&quot;&gt;BatteryCallback&lt;/span&gt; &lt;/span&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;meta&quot;&gt;@Override&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;activityIdle&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(IBinder token, Configuration config, &lt;span class=&quot;keyword&quot;&gt;boolean&lt;/span&gt; stopProfiling)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;long&lt;/span&gt; origId = Binder.clearCallingIdentity();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;synchronized&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ActivityStack stack = ActivityRecord.getStackLocked(token);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (stack != &lt;span class=&quot;keyword&quot;&gt;null&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ActivityRecord r =&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        mStackSupervisor.activityIdleInternalLocked(token, &lt;span class=&quot;keyword&quot;&gt;false&lt;/span&gt;, config);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (stopProfiling) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((mProfileProc == r.app) &amp;amp;&amp;amp; (mProfileFd != &lt;span class=&quot;keyword&quot;&gt;null&lt;/span&gt;)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;try&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            mProfileFd.close();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;catch&lt;/span&gt; (IOException e) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        clearProfilerLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Binder.restoreCallingIdentity(origId);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;ActivityManagerService有一个类型为ActivityStackSupervisor的成员变量mStackSupervisor，Run all ActivityStacks through this，运行所有的ActivityStacks 通过这个，它的成员函数activityIdleInternalLocked如下：&lt;br&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// Checked.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt; ActivityRecord &lt;span class=&quot;title&quot;&gt;activityIdleInternalLocked&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt; IBinder token, &lt;span class=&quot;keyword&quot;&gt;boolean&lt;/span&gt; fromTimeout,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Configuration config)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;boolean&lt;/span&gt; booting = &lt;span class=&quot;keyword&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;boolean&lt;/span&gt; enableScreen = &lt;span class=&quot;keyword&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;boolean&lt;/span&gt; activityRemoved = &lt;span class=&quot;keyword&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ActivityRecord r = ActivityRecord.forToken(token);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (r != &lt;span class=&quot;keyword&quot;&gt;null&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (isFrontStack(r.task.stack) || fromTimeout) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            booting = mService.mBooting;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mService.mBooting = &lt;span class=&quot;keyword&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mService.mBooted) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mService.mBooted = &lt;span class=&quot;keyword&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                enableScreen = &lt;span class=&quot;keyword&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (booting || enableScreen) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mService.postFinishBooting(booting, enableScreen);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; r;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以进入if判断中，将booting置为true，mService.mBooted和enableScreen也为true，进入下面的if判断，ActivityManagerService调用postFinishBooting方法完成系统启动。我们进入往下看：&lt;br&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;postFinishBooting&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;boolean&lt;/span&gt; finishBooting, &lt;span class=&quot;keyword&quot;&gt;boolean&lt;/span&gt; enableScreen)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mHandler.sendMessage(mHandler.obtainMessage(FINISH_BOOTING_MSG,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            finishBooting? &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt; : &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, enableScreen ? &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt; : &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt; MainHandler mHandler;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;MainHandler&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Handler&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;meta&quot;&gt;@Override&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;handleMessage&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(Message msg)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; FINISH_BOOTING_MSG: &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (msg.arg1 != &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                finishBooting();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (msg.arg2 != &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                enableScreenAfterBoot();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里最后调用enableScreenAfterBoot方法，以便可以将屏幕让出来显示应用程序Launcher的界面：&lt;br&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;enableScreenAfterBoot&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            SystemClock.uptimeMillis());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mWindowManager.enableScreenAfterBoot();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;synchronized&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        updateEventDispatchingLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;ActivityManagerService类的成员变量mWindowManager指向了系统中的Window管理服务WindowManagerService，ActivityManagerService服务通过调用它的成员函数enableScreenAfterBoot来停止显示开机动画。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WindowManagerService类的成员函数enableScreenAfterBoot的实现如下所示：&lt;br&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;enableScreenAfterBoot&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;synchronized&lt;/span&gt;(mWindowMap) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (DEBUG_BOOT) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            RuntimeException here = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; RuntimeException(&lt;span class=&quot;string&quot;&gt;&quot;here&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            here.fillInStackTrace();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Slog.i(TAG, &lt;span class=&quot;string&quot;&gt;&quot;enableScreenAfterBoot: mDisplayEnabled=&quot;&lt;/span&gt; + mDisplayEnabled&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    + &lt;span class=&quot;string&quot;&gt;&quot; mForceDisplayEnabled=&quot;&lt;/span&gt; + mForceDisplayEnabled&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    + &lt;span class=&quot;string&quot;&gt;&quot; mShowingBootMessages=&quot;&lt;/span&gt; + mShowingBootMessages&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    + &lt;span class=&quot;string&quot;&gt;&quot; mSystemBooted=&quot;&lt;/span&gt; + mSystemBooted, here);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mSystemBooted) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSystemBooted = &lt;span class=&quot;keyword&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        hideBootMessagesLocked();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// If the screen still doesn&#39;t come up after 30 seconds, give&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// up and turn it on.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, &lt;span class=&quot;number&quot;&gt;30&lt;/span&gt;*&lt;span class=&quot;number&quot;&gt;1000&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mPolicy.systemBooted();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    performEnableScreen();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WindowManagerService类的成员变量mSystemBooted用来记录系统是否已经启动完成的。如果已经启动完成的话，那么这个成员变量的值就会等于true，这时候WindowManagerService类的成员函数enableScreenAfterBoot什么也不做就返回了，否则的话，WindowManagerService类的成员函数enableScreenAfterBoot首先将这个成员变量的值设置为true，接着再调用另外一个成员函数performEnableScreen来执行停止显示开机动画的操作。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WindowManagerService类的成员函数performEnableScreen的实现如下所示：&lt;br&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;performEnableScreen&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;synchronized&lt;/span&gt;(mWindowMap) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mDisplayEnabled) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mSystemBooted &amp;amp;&amp;amp; !mShowingBootMessages) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Don&#39;t enable the screen until all existing windows have been drawn.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mForceDisplayEnabled &amp;amp;&amp;amp; checkWaitingForWindowsLocked()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!mBootAnimationStopped) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// Do this one time.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;try&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                IBinder surfaceFlinger = ServiceManager.getService(&lt;span class=&quot;string&quot;&gt;&quot;SurfaceFlinger&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (surfaceFlinger != &lt;span class=&quot;keyword&quot;&gt;null&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//Slog.i(TAG, &quot;******* TELLING SURFACE FLINGER WE ARE BOOTED!&quot;);&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    Parcel data = Parcel.obtain();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    data.writeInterfaceToken(&lt;span class=&quot;string&quot;&gt;&quot;android.ui.ISurfaceComposer&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, &lt;span class=&quot;comment&quot;&gt;// BOOT_FINISHED&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            data, &lt;span class=&quot;keyword&quot;&gt;null&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    data.recycle();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;keyword&quot;&gt;catch&lt;/span&gt; (RemoteException ex) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                Slog.e(TAG, &lt;span class=&quot;string&quot;&gt;&quot;Boot completed: SurfaceFlinger is dead!&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mBootAnimationStopped = &lt;span class=&quot;keyword&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;WindowManagerService类的另外一个成员变量mDisplayEnabled用来描述WindowManagerService是否已经初始化过系统的屏幕了，只有当它的值等于false，并且系统已经完成启动，即WindowManagerService类的成员变量mSystemBooted等于true的情况下，WindowManagerService类的成员函数performEnableScreen才通知SurfaceFlinger服务停止显示开机动画。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;注意，WindowManagerService类的成员函数performEnableScreen是通过一个类型为IBinder.FIRST_CALL_TRANSACTION的进程间通信请求来通知SurfaceFlinger服务停止显示开机动画的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在SurfaceFlinger服务，类型为IBinder.FIRST_CALL_TRANSACTION的进程间通信请求被定义为停止显示开机动画的请求，位于frameworks/native/include/gui/ISurfaceComposer.h中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; BnSurfaceComposer : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; BnInterface&amp;lt;ISurfaceComposer&amp;gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;enum&lt;/span&gt; &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Note: BOOT_FINISHED must remain this value, it is called from  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// Java by ActivityManagerService.  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; status_t    &lt;span class=&quot;title&quot;&gt;onTransact&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;( &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; code,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Parcel&amp;amp; data,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                    Parcel* reply,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;BnSurfaceComposer类它是SurfaceFlinger服务所要继承的Binder本地对象类，其中。当SurfaceFlinger服务接收到类型为IBinder::FIRST_CALL_TRANSACTION，即类型为BOOT_FINISHED的进程间通信请求时，它就会将该请求交给它的成员函数bootFinished来处理。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceFlinger服务的成员函数bootFinished实现在文件frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::bootFinished()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; now = systemTime();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;nsecs_t&lt;/span&gt; duration = now - mBootTime;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGI(&lt;span class=&quot;string&quot;&gt;&quot;Boot is finished (%ld ms)&quot;&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;long&lt;/span&gt;(ns2ms(duration)) );&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mBootFinished = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// wait patiently for the window manager death&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; String16 &lt;span class=&quot;title&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;string&quot;&gt;&quot;window&quot;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;IBinder&amp;gt; window(defaultServiceManager()-&amp;gt;getService(name));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (window != &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        window-&amp;gt;linkToDeath(&lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;IBinder::DeathRecipient*&amp;gt;(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// stop boot animation&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// formerly we would just kill the process, but we now ask it to exit so it&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// can choose where to stop the animation.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    property_set(&lt;span class=&quot;string&quot;&gt;&quot;service.bootanim.exit&quot;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&quot;1&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;可以看到，该函数将属性“service.bootanim.exit”设置为”1”。在第2节分析android()代码的时候，我们讲到：当属性“service.bootanim.exit”值被设为”1”时，android()就会退出，开机动画显示自然也就结束了。由于android()退出且返回值为false，BootAnimation::threadLoop()线程也就结束了。再回到BootAnimation.cpp的main()函数中，threadLoop()线程结束，main函数也就结束，至此，bootanimaiton进程就自行结束，开机动画的显示完成了。 &lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;至此，Android系统的三个开机画面的显示过程就分析完成了。&lt;/p&gt;
&lt;h1 id=&quot;小结&quot;&gt;&lt;a href=&quot;#小结&quot; class=&quot;headerlink&quot; title=&quot;小结&quot;&gt;&lt;/a&gt;小结&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;本文的目的并不是单纯为了介绍Android系统的开机画面，而是希望能够以Android系统的开机画面来作为切入点来分析SurfaceFlinger。后续文章我们会详细分析SurfaceFlinger的每个模块和功能。没图了，等过一阵子再去拍一波~&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%B8%89%29----Android%E5%BC%80%E6%9C%BA%E5%8A%A8%E7%94%BB%E6%B5%81%E7%A8%8B%E7%AE%80%E8%BF%B0/mm.jpg&quot; alt=&quot;妹子&quot;&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在详细分析SurfaceFlinger模块之前要先看看Android的开机动画，因为这个BootAnimation是一个C++应用程序，需要使用SurfaceFlinger服务来创建和渲染自己的Surface，并且不涉及与用户进行交互，所以能以最简洁的方式体现Android与SurfaceFlinger服务的关系。&lt;br&gt;
    
    </summary>
    
      <category term="Android技术点" scheme="http://windrunnerlihuan.com/categories/Android%E6%8A%80%E6%9C%AF%E7%82%B9/"/>
    
    
      <category term="SurfaceFlinger" scheme="http://windrunnerlihuan.com/tags/SurfaceFlinger/"/>
    
  </entry>
  
  <entry>
    <title>Android SurfaceFlinger 学习之路(二)----SurfaceFlinger概述</title>
    <link href="http://windrunnerlihuan.com/2017/04/27/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%BA%8C-SurfaceFlinger%E6%A6%82%E8%BF%B0/"/>
    <id>http://windrunnerlihuan.com/2017/04/27/Android-SurfaceFlinger-学习之路-二-SurfaceFlinger概述/</id>
    <published>2017-04-27T09:28:11.000Z</published>
    <updated>2019-01-06T07:28:43.052Z</updated>
    
    <content type="html">&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;因为还有很多烦人的事情需要处理，所以暂时没有离职，也挺忙的。最近一段时间稍微轻松些，所以更新一下这个进度。&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Android的Graphic系统是设计的很精妙，但是也很复杂。SurfaceFlinger也是Graphic系统中十分重要的组成部分，要从正面分析不是一件容易的事情。所以我们先从侧面窥视它的重要模块，积累起足够的模块基础，再统一分析，就会一目了然。&lt;/p&gt;
&lt;h1 id=&quot;GUI框架&quot;&gt;&lt;a href=&quot;#GUI框架&quot; class=&quot;headerlink&quot; title=&quot;GUI框架&quot;&gt;&lt;/a&gt;GUI框架&lt;/h1&gt;&lt;h2 id=&quot;图形显示过程&quot;&gt;&lt;a href=&quot;#图形显示过程&quot; class=&quot;headerlink&quot; title=&quot;图形显示过程&quot;&gt;&lt;/a&gt;图形显示过程&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;一般应用开发都要将UI数据使用Activity这个载体去展示，典型的Activity显示流程为：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;startActivity启动Activity；&lt;/li&gt;
&lt;li&gt;为Activity创建一个window(PhoneWindow)，并在WindowManagerService中注册这个window；&lt;/li&gt;
&lt;li&gt;切换到前台显示时，WindowManagerService会要求SurfaceFlinger为这个window创建一个surface用来绘图。SurfaceFlinger创建一个”layer”（surface）。（以想象一下C/S架构，SF对应Server，对应Layer；App对应Client，对应Surface）,这个layer的核心即是一个BufferQueue，这时候app就可以在这个layer上render了；&lt;/li&gt;
&lt;li&gt;将所有的layer进行合成，显示到屏幕上。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;一般app而言，在任何屏幕上起码有三个layer：屏幕顶端的status bar，屏幕下面的navigation bar，还有就是app的UI部分。&lt;/strong&gt;一些特殊情况下，app的layer可能多余或者少于3个，例如对全屏显示的app就没有status bar，而对launcher，还有个为了wallpaper显示的layer。status bar和navigation bar是由系统进行去render，因为不是普通app的组成部分嘛。而app的UI部分对应的layer当然是自己去render，所以就有了第4条中的所有layer进行“合成”。 &lt;/p&gt;
&lt;h2 id=&quot;GUI框架-1&quot;&gt;&lt;a href=&quot;#GUI框架-1&quot; class=&quot;headerlink&quot; title=&quot;GUI框架&quot;&gt;&lt;/a&gt;GUI框架&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/file/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%8C%29----SurfaceFlinger%E6%A6%82%E8%BF%B0/gui.jpg&quot; alt=&quot;GUI&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceFlinger：每当用户程序刷新UI的时候，会中介BufferQueue申请一个buffer（dequeueBuffer），然后把UI的信息填入，丢给SurfaceFlinger，SurfaceFlinger通过计算多重计算合成visibleRegion之后，丢给openGL层处理，处理之后送到显示器display上显示。&lt;/p&gt;
&lt;p&gt;根据整个Android系统的GUI设计理念，我们不难猜想到至少需要两种本地窗口：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;面向管理者(SurfaceFlinger)：既然SurfaceFlinger扮演了系统中所有UI界面的管理者，那么它无可厚非地需要直接或间接地持有“本地窗口”，这个窗口就是FramebufferNativeWindow&lt;/li&gt;
&lt;li&gt;面向应用程序：这类窗口是Surface（这里和以前版本出入比较大，之前的版本本地窗口是SurfaceTextureClient）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;第二种窗口是能直接显示在终端屏幕上的——它使用了帧缓冲区，而第一种Window实际上是从内存缓冲区分配的空间。当系统中存在多个应用程序时，这能保证它们都可以获得一个“本地窗口”，并且这些窗口最终也能显示到屏幕上——SurfaceFlinger会收集所有程序的显示需求，对它们做统一的图像混合操作。&lt;/p&gt;
&lt;h1 id=&quot;Render过程&quot;&gt;&lt;a href=&quot;#Render过程&quot; class=&quot;headerlink&quot; title=&quot;Render过程&quot;&gt;&lt;/a&gt;Render过程&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;android提供了两种方式：Canvas ，OpenGL ES。这两种方式在我认为都应该算是标准，提供了一套固定的API，实现和平台无关。Java中类似于给你提供了一个interface接口，这个接口你可以用任何方式去实现，只要满足功能要求即可。不同的人可以有不同的实现方式，对10个数进行排序，A可以用冒泡法，B可以用选择法，最终结果只要保证把这10个数排好序了，唯一差别就是实现难度和效率问题。&lt;/p&gt;
&lt;h2 id=&quot;Canvas&quot;&gt;&lt;a href=&quot;#Canvas&quot; class=&quot;headerlink&quot; title=&quot;Canvas&quot;&gt;&lt;/a&gt;Canvas&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;android提供了Canvas 2D API用来进行普通图形的绘制的，类似TextView这种应该都是用Canvas API来完成的。而Canvas这个”标准”的具体实现是由/external/skia库来完成的，真正干活的是skia。&lt;strong&gt;上层Canvas调用的API到下层其实封装了skia的实现。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;OpenGL-ES&quot;&gt;&lt;a href=&quot;#OpenGL-ES&quot; class=&quot;headerlink&quot; title=&quot;OpenGL ES&quot;&gt;&lt;/a&gt;OpenGL ES&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;OpenGL ES相关的API是为了3D图形的绘制而准备的。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;android上有个EGL库，EGL和OpenGL ES是什么关系？代码在frameworks\native\opengl\libs\，我们查看frameworks\native\opengl\libs\Android.mk中：&lt;br&gt;&lt;figure class=&quot;highlight makefile&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;LOCAL_SHARED_LIBRARIES += libcutils libutils liblog libGLES_trace&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;#编译的库文件为/system/lib/libEGL.so&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;LOCAL_MODULE:= libEGL&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;LOCAL_LDFLAGS += -Wl,--exclude-libs=ALL&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;LOCAL_SHARED_LIBRARIES += libdl&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# we need to access the private Bionic header &amp;lt;bionic_tls.h&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;LOCAL_C_INCLUDES += bionic/libc/private&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;......&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;SurfaceFlinger这个非常重要的系统服务依赖EGL库，包含了EGL头文件，使用了EGL中的函数，查看frameworks/native/services/surfaceflinger/Android.mk：&lt;br&gt;&lt;figure class=&quot;highlight makefile&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;LOCAL_SHARED_LIBRARIES := \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    libcutils \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    liblog \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    libdl \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    libhardware \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    libutils \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    libEGL \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    libGLESv1_CM \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    libGLESv2 \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    libbinder \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    libui \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    libgui \&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    libpowermanager&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;LOCAL_MODULE:= libsurfaceflinger&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;include $(BUILD_SHARED_LIBRARY)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;......&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在SurfaceFlinger::init()中，调用了egl开头的函数，位于frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SurfaceFlinger::init() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGI(  &lt;span class=&quot;string&quot;&gt;&quot;SurfaceFlinger&#39;s main thread ready to run. &quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;string&quot;&gt;&quot;Initializing graphics H/W...&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::Autolock _l(mStateLock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// initialize EGL for the default display&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//#define EGL_DEFAULT_DISPLAY       ((EGLNativeDisplayType)0)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    eglInitialize(mEGLDisplay, &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;, &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在eglGetDisplay()中调用了egl_init_drivers()，位于frameworks/native/opengl/libs/egl/eglApi.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;EGLDisplay &lt;span class=&quot;title&quot;&gt;eglGetDisplay&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(EGLNativeDisplayType display)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    clearError();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uintptr_t&lt;/span&gt; index = &lt;span class=&quot;keyword&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;uintptr_t&lt;/span&gt;&amp;gt;(display);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (index &amp;gt;= NUM_DISPLAYS) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//egl_init_drivers函数载入OpenGL ES相关库&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (egl_init_drivers() == EGL_FALSE) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    EGLDisplay dpy = &lt;span class=&quot;keyword&quot;&gt;egl_display_t&lt;/span&gt;::getFromNativeDisplay(display);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; dpy;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;关于egl_init_drivers()函数，载入OpenGL ES相关库，限于本篇只是简单介绍，所以不详细分析。相关文件如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;frameworks/native/opengl/libs/egl/Egl.cpp&lt;/li&gt;
&lt;li&gt;frameworks/native/opengl/libs/egl/Loader.cpp&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;代码也不多，主要做的事情：&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1. 首先在frameworks\native\opengl\libs\EGL\egl_entries.in中保存了EGL的相关API，函数都是以egl开头；在frameworks\native\opengl\libs\entries.in中保存了OpenGL ES相关API，函数都是以gl开头。函数egl_init_drivers()需要做的就是找到EGL和OpenGL ES本地的实现，然后对这些函数进行赋值。可以查看frameworks/native/opengl/libs/egl/Egl.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; * &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; gl_names[] = &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    #include &lt;span class=&quot;string&quot;&gt;&quot;../entries.in&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; * &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; egl_names[] = &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    #include &lt;span class=&quot;string&quot;&gt;&quot;egl_entries.in&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2. &lt;strong&gt;在/vendor/lib/egl或/system/lib/egl下(不是/system/lib/下)，寻找libGLES.so，如果未找到，则寻找libGLES_*.so&lt;/strong&gt;，上面两种库只要找到一个，则打开库，这个库里包含了EGL和OpenGL ES具体实现的库，然后“取出”库中具体的函数实现进行赋值。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;但是较新版本的android已经不使用软件实现，即libagl，所以即使找到libGLES_android.so也不会去用。位于frameworks/native/opengl/libs/egl/Loader.cpp中load_driver函数实现：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; *Loader::load_driver(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt;* kind,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;egl_connection_t&lt;/span&gt;* cnx, &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; mask)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!&lt;span class=&quot;built_in&quot;&gt;strcmp&lt;/span&gt;(e-&amp;gt;d_name, &lt;span class=&quot;string&quot;&gt;&quot;libGLES_android.so&quot;&lt;/span&gt;)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;comment&quot;&gt;// always skip the software renderer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; ......                   &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果libGLES.so和libGLES_&lt;em&gt;.so都未找到，需要分别去加载/vendor/lib/egl或/system/lib/egl下libEGL.so, libGLESv1&lt;em&gt;CM.so, libGLESv2.so这三个库或者libEGL&lt;/em&gt;&lt;/em&gt;.so, libGLESv1&lt;em&gt;CM&lt;/em&gt;&lt;em&gt;.so, libGLESv2_&lt;/em&gt;.so，然后分别对EGL、OpenGL ES V1、OpenGL ES V2的具体实现去赋值(&lt;strong&gt;那意思是libGLES_*.so中其实囊括了三个库所有的具体实现&lt;/strong&gt;)。至此，就将OpenGL ES“标准”和“实现”挂钩了。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以android中OpenGL ES的实现方式有2种：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一种是软件实现，用cpu去绘图，这就是所谓的agl(libGLES_android.so)，代码路径在frameworks/native/opengl/libagl，即the software OpenGL ES library；&lt;/li&gt;
&lt;li&gt;另一种是硬件厂商根据自己GPU提供的实现，一般都不开放源代码，就是上面介绍的需要去/vendor/lib/egl或/system/lib/egl找的几个库，但是只要把API 函数赋值上正确的实现函数即可。 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;此外由于OpenGL ES的实现是系统无关的，所以EGL库的另一个作用就是将OpenGL ES和本地窗口系统结合起来，举个例子好理解，如果你要画个纹理多边形，调用OpenGL ES接口，如果要把图形render到屏幕，需要调用EGL接口。例如在使用OpenGL ES前首先需要调用EGL的相关函数去搭建好OpenGL ES的本地环境等，EGL是android使用OpenGL ES API绘图的助手！&lt;/p&gt;
&lt;h2 id=&quot;hardware-accelerated-Canvas&quot;&gt;&lt;a href=&quot;#hardware-accelerated-Canvas&quot; class=&quot;headerlink&quot; title=&quot;hardware-accelerated Canvas&quot;&gt;&lt;/a&gt;hardware-accelerated Canvas&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从android 4.0开始，支持了硬件加速的Canvas，应该就是修改了Canvas的具体实现，不用skia了，而改调用EGL和OpenGL ES API了。&lt;/p&gt;
&lt;h2 id=&quot;android的封装&quot;&gt;&lt;a href=&quot;#android的封装&quot; class=&quot;headerlink&quot; title=&quot;android的封装&quot;&gt;&lt;/a&gt;android的封装&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;那么我们平时写app时为何不用调用上面的Canvas和OpenGL ES，也能出现漂亮的UI呢？因为我们使用的都是android上层封装好的类，例如TextView就是用了Canvas，而GLSurfaceView就是使用了OpenGL ES，android已经帮我们做了大部分的工作。当然完全可以不用调用上层的Java类，而用c++/c去直接调用Canvas和OpenGL ES。 &lt;/p&gt;
&lt;h1 id=&quot;如何去合成&quot;&gt;&lt;a href=&quot;#如何去合成&quot; class=&quot;headerlink&quot; title=&quot;如何去合成&quot;&gt;&lt;/a&gt;如何去合成&lt;/h1&gt;&lt;p&gt;首先介绍个概念，&lt;strong&gt;hardware overlay&lt;/strong&gt;，来自&lt;a href=&quot;https://en.wikipedia.org/wiki/Hardware_overlay&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;维基百科&lt;/a&gt;。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;From Wikipedia, the free encyclopedia&lt;br&gt;In computing, hardware overlay, a type of video overlay, provides a method of rendering an image to a display screen with a dedicated memory buffer inside computer video hardware. The technique aims to improve the display of a fast-moving video image — such as a computer game, a DVD, or the signal from a TV card. Most video cards manufactured since about 1998 and most media players support hardware overlay.[1]&lt;/p&gt;
&lt;p&gt;The overlay is a dedicated buffer into which one app can render (typically video), without incurring the significant performance cost of checking for clipping and overlapping rendering by other apps. The framebuffer has hardware support for importing and rendering the buffer contents without going through the GPU.[citation needed]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;hardware overlay 是提供一种机制，直接render到display screen的硬件内存中，提高显示效率吧。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;而android对layer的合成主要包括2部分：在GPU中合成和在display的硬件中进行buffer的合成。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;在GPU中进行合成，既是利用OpenGL ES进行合成，需要注意，画图的时候我们用了OpenGL ES，这里合成时也用了，功能真是强大，开始一直奇怪为何SurfaceFlinger也要去调用EGL的函数，原来是需要用OpenGL ES去合成layer&lt;/strong&gt;；在display的硬件中进行合成，也就是hardware overlay机制。&lt;/p&gt;
&lt;h2 id=&quot;Hardware-Composer&quot;&gt;&lt;a href=&quot;#Hardware-Composer&quot; class=&quot;headerlink&quot; title=&quot;Hardware Composer&quot;&gt;&lt;/a&gt;Hardware Composer&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;那么android是如何使用这两种合成机制的呢？这里就是Hardware Composer的功劳。处理流程为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1.SurfaceFlinger给HWC提供layer list，询问如何处理这些layer；&lt;/li&gt;
&lt;li&gt;2.HWC将每个layer标记为overlay或者GLES composition，然后回馈给SurfaceFlinger；&lt;/li&gt;
&lt;li&gt;3.SurfaceFlinger需要去处理那些GLES的合成，而不用去管overlay的合成，最后将overlay的layer和GLES合成后的buffer发送给HWC处理。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;借用google一张图说明，可以将上面讲的很多概念展现，很清晰。地址位于 &lt;a href=&quot;https://source.android.com/devices/graphics/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;https://source.android.com/devices/graphics/&lt;/a&gt;&lt;br&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/file/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%8C%29----SurfaceFlinger%E6%A6%82%E8%BF%B0/hw.png&quot; alt=&quot;合成&quot;&gt;&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;在我认为使用overlay后，可以将SurfaceFlinger的工作减轻，即少一些GLES的合成，HWC承担了部分OpenGL ES 和GPU的工作， 从而减少了功耗。&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;注：如果屏幕上的画面基本不变化，这时候用GLES 合成的效率要高于overlay(overlay主要是为了render快速变化的图形等)；android 4.4往上支持4个oveylay，如果要合成超过4个layer，系统就会对剩余的使用GLES合成，所以app的layer个数对手机的功耗影响挺大。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&quot;SurfaceFlinger和BufferQueue&quot;&gt;&lt;a href=&quot;#SurfaceFlinger和BufferQueue&quot; class=&quot;headerlink&quot; title=&quot;SurfaceFlinger和BufferQueue&quot;&gt;&lt;/a&gt;SurfaceFlinger和BufferQueue&lt;/h1&gt;&lt;h2 id=&quot;生产模型&quot;&gt;&lt;a href=&quot;#生产模型&quot; class=&quot;headerlink&quot; title=&quot;生产模型&quot;&gt;&lt;/a&gt;生产模型&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;一个UI完全显示到diplay的过程，SurfaceFlinger扮演着重要的角色但是它的职责是“Flinger”，即把系统中所有应用程序的最终的“绘图结果”进行“混合”，然后统一显示到物理屏幕上，而其他方面比如各个程序的绘画过程，就由其他东西来担任了。这个光荣的任务自然而然地落在了BufferQueue的肩膀上，它是每个应用程序“一对一”的辅导老师，指导着UI程序的“画板申请”、“作画流程”等一系列细节。下面的图描述了这三者的关系：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/file/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%8C%29----SurfaceFlinger%E6%A6%82%E8%BF%B0/PC1.jpg&quot; alt=&quot;P/C&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;虽说是三者的关系，但是他们所属的层却只有两个，app属于Java层，BufferQueue/SurfaceFlinger属于native层。也就是说BufferQueue也是隶属SurfaceFlinger，所有工作围绕SurfaceFlinger展开。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里IGraphicBufferProducer就是app和BufferQueue重要桥梁，GraphicBufferProducer承担着单个应用进程中的UI显示需求，与BufferQueue打交道的就是它。它的工作流程如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/file/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%8C%29----SurfaceFlinger%E6%A6%82%E8%BF%B0/PC2.jpg&quot; alt=&quot;P/C&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;BpGraphicBufferProducer是GraphicBufferProducer在客户端这边的代理对象，负责和SF交互，GraphicBufferProducer通过gbp（IGraphicBufferProducer类对象）向BufferQueue获取buffer，然后进行填充UI信息，当填充完毕会通知SF，SF知道后就对该Buffer进行下一步操作。&lt;strong&gt;典型的生产-消费者模式&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id=&quot;工作流程&quot;&gt;&lt;a href=&quot;#工作流程&quot; class=&quot;headerlink&quot; title=&quot;工作流程&quot;&gt;&lt;/a&gt;工作流程&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接下来具体说明客户端（producer）和服务端SurfaceFlinger（consumer）工作的模式：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;首先这里的buffer是共享缓冲区，故肯定会涉及到互斥锁，所以buffer的状态也会有多种，一般的buffer大致会经过&lt;strong&gt;FREE-&amp;gt;DEQUEUED-&amp;gt;QUEUED-&amp;gt;ACQUIRED-&amp;gt;FREE&lt;/strong&gt;这个流程，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/file/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%8C%29----SurfaceFlinger%E6%A6%82%E8%BF%B0/PC3.jpg&quot; alt=&quot;P/C&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;BufferQueue&lt;/strong&gt;：可以认为BufferQueue是一个服务中心，其它两个owner必须要通过它来管理buffer。比如说当producer想要获取一个buffer时，它不能越过BufferQueue直接与consumer进行联系，反之亦然。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Producer&lt;/strong&gt;：生产者就是“填充”buffer空间的人，通常情况下当然就是应用程序。因为应用程序不断地刷新UI，从而将产生的显示数据源源不断地写到buffer中。当Producer需要使用一块buffer时，它首先会向中介BufferQueue发起dequeue申请，然后才能对指定的缓冲区进行操作。这种情况下buffer就属于producer一个人的了，它可以对buffer进行任何必要的操作，而其它owner此刻绝不能擅自插手。&lt;br&gt;当生产者认为一块buffer已经写入完成后，它进一步调用BufferQueue的queue。从字面上看这个函数是“入列”的意思，形象地表达了buffer此时的操作——把buffer归还到BufferQueue的队列中。一旦queue成功后，owner也就随之改变为BufferQueue了。&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consumer&lt;/strong&gt;：消费者是与生产者相对应的，它的操作同样受到BufferQueue的管控。当一块buffer已经就绪后，Consumer就可以开始工作了。这里需要特别留意的是，从各个对象所扮演的角色来看，BufferQueue是中介机构，属于服务提供方;Producer属于buffer内容的产出方，它对缓冲区的操作是一个“主动”的过程;反之，Consumer对buffer的处理则是“被动”的、“等待式”的——它必须要等到一块buffer填充完成后才能做工作。在这样的模型下，我们怎么保证Consumer可以及时的处理buffer呢？换句话说，当一块buffer数据ready后，应该怎么告知Consumer来操作呢？&lt;br&gt;仔细观察的话，可以看到BufferQueue里还同时提供了一个特别的类，名称为ProxyConsumerListener，其中的函数接口包括：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;classProxyConsumerListener : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; BnConsumerListener &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;:       &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;comment&quot;&gt;//省略构造函数  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;onFrameAvailable&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;;&lt;span class=&quot;comment&quot;&gt;/*当一块buffer可以被消费时，这个函数会被调用，特别注意此时没有共享锁的保护*/&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;voidonBuffersReleased&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;;&lt;span class=&quot;comment&quot;&gt;/*BufferQueue通知consumer它已经释放其slot中的一个或多个 GraphicBuffer引用*/&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;:  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   wp&amp;lt;ConsumerListener&amp;gt;mConsumerListener;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;这样子就很清楚了，当有一帧数据准备就绪后，BufferQueue就会调用onFrameAvailable()来通知Consumer进行消费。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;消费模型&quot;&gt;&lt;a href=&quot;#消费模型&quot; class=&quot;headerlink&quot; title=&quot;消费模型&quot;&gt;&lt;/a&gt;消费模型&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;BufferQueue和SurfaceFlinger之间的通信模式如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/file/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%8C%29----SurfaceFlinger%E6%A6%82%E8%BF%B0/consumer.jpg&quot; alt=&quot;Consumer&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;也是有一对BpGraphicBufferConsumer/BnGraphicBufferConsumer支持他们之间的信息传输。&lt;/p&gt;
&lt;h1 id=&quot;结语&quot;&gt;&lt;a href=&quot;#结语&quot; class=&quot;headerlink&quot; title=&quot;结语&quot;&gt;&lt;/a&gt;结语&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;本篇只是简单科普一下SurfaceFlinger的轮廓，我们从下一篇开始详细分析每个流程。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;突然觉得上一篇开头太中二了=。= 唉，事情太多了，有点烦，感觉没了以前那份心若冰清的沉稳和奋不顾身的勇气了，唉(第二次唉)，慢慢来，需要时间去消化。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/file/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%BA%8C%29----SurfaceFlinger%E6%A6%82%E8%BF%B0/meizi.jpg&quot; alt=&quot;妹子&quot;&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;因为还有很多烦人的事情需要处理，所以暂时没有离职，也挺忙的。最近一段时间稍微轻松些，所以更新一下这个进度。&lt;br&gt;
    
    </summary>
    
      <category term="Android技术点" scheme="http://windrunnerlihuan.com/categories/Android%E6%8A%80%E6%9C%AF%E7%82%B9/"/>
    
    
      <category term="SurfaceFlinger" scheme="http://windrunnerlihuan.com/tags/SurfaceFlinger/"/>
    
  </entry>
  
  <entry>
    <title>Android性能优化之内存优化实战</title>
    <link href="http://windrunnerlihuan.com/2017/04/07/Android%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96%E5%AE%9E%E6%88%98/"/>
    <id>http://windrunnerlihuan.com/2017/04/07/Android性能优化之内存优化实战/</id>
    <published>2017-04-07T11:10:11.000Z</published>
    <updated>2019-01-06T07:26:58.593Z</updated>
    
    <content type="html">&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;事情依旧很多，生活的、工作的，成长总是需要代价的。一直憧憬童年和大学，那是两种异曲同工的生活态度。假装自己是个孩子，一直不想长大，被自己小小的愿望襁褓着，不去理会外面世界的沧海桑田。白驹过隙，岁月在脸上留下了痕迹，不再隐瞒早已不年轻的事实。伴随着时光点滴流逝，心也在渐渐老去。也许成长就是一种淡然吧，从锋芒毕露到心如止水，从棱角分明到不露声色。少了昔日偶尔破釜沉舟的勇气，更多的是经常瞻前顾后的思虑。时光荏苒，没有留下刻骨铭心的记忆，更多的是平淡、安静。我渐渐喜欢这种感觉，岁月静好，没有跌宕起伏的生活剧情，没有扣人心弦的情景环节，一切安好，便是生活最美好的恩赐。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;记忆渐渐模糊，没有留下印记。没有选择性忘记，但却真实在一点一点消逝。那些旧照片也没能留下，早已不见了踪影，那些故人，都逐渐失去了联系，那些雨天泥泞的小路，还有路边在儿时植树节时新栽的小树，也都变得那么陌生。只有那些花儿，却开的愈加鲜艳茂密。就像一颗顽强的心，一颗不服输的心，在抗拒随波逐流的人生。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;多年之前，我们都还是个孩子。经过岁月的洗礼，也许会变得更加沉稳，也会变得更加冷静，亦或者是……冷漠。回忆往昔，这一路走来，还是渐渐变成了孩时最讨厌的自己，一个冷漠的自己，一个绝情的自己。安静也许是一个借口，一种掩饰，透过镜子，终于看清了真实的自己，那个自私的自己。有人说，社会会逼着一个人成长，是啊，虽然不愿承认，但是至少褪去了青年时怕事嫌烦表选出来的虚伪，获得更多的是学会了处事不惊的态度，和勇于承担责任的勇气。如果选择对生活妥协，是不会答应的，即使没了追梦赤子心，至少还有追逐本心的动力。不忘初心，坚持自己的初衷。青春即使如同《老男孩》的歌词唱的那样：”青春如同奔流的江河,一去不回来不及道别,只剩下麻木的我,没有了当年的热血……”即便如此，依然要做不一样的我，一个不退缩、不妥协的我，一个默默前行的我，一个坚持本心的我————“我就是我，是颜色不一样的烟火，天空海阔，要做最坚强的泡沫，我喜欢我，让蔷薇开出一种结果，孤独的沙漠里一样盛放的赤裸裸”&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这次带来一篇性能优化的文章，内容来自&lt;code&gt;APP架构师&lt;/code&gt;,我稍微修改了一些部分，加了一些内容。&lt;/p&gt;
&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;
&lt;h1 id=&quot;Memory-Leak&quot;&gt;&lt;a href=&quot;#Memory-Leak&quot; class=&quot;headerlink&quot; title=&quot;Memory Leak&quot;&gt;&lt;/a&gt;Memory Leak&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;内存泄漏：对于Java来说，就是new出来的Object 放在Heap上无法被GC回收（内存中存在无法被回收的对象）；内存泄漏发生时的主要表现为内存抖动，可用内存慢慢变少。&lt;/p&gt;
&lt;h2 id=&quot;Memory-Monitor&quot;&gt;&lt;a href=&quot;#Memory-Monitor&quot; class=&quot;headerlink&quot; title=&quot;Memory Monitor&quot;&gt;&lt;/a&gt;Memory Monitor&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;AndroidStudio自带的Memory Monitor可以方便的观察堆内存的分配情况，并且可以粗略的观察有没有Memory Leak。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96%E5%AE%9E%E6%88%98/arrow.jpg&quot; alt=&quot;内存显示&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;频繁的内存抖动，可能存在内存泄漏&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A：initiate GC 手动触发GC操作；&lt;/li&gt;
&lt;li&gt;B：Dump Java Heap 获取当前的堆栈信息，生成一个.hprof文件，AndroidStudip会自动使用HeapViewer打开；一般用于操作之后检测内存泄漏的情况；&lt;/li&gt;
&lt;li&gt;C：Start Allocation Tracking 内存分配追踪工具，用于追踪一段时间的内存分配使用情况，能够知道执行一些列操作后，有哪些对象被分配空间。一般用于追踪某项操作之后的内存分配，调整相关的方法调用来优化app性能与内存使用；&lt;/li&gt;
&lt;li&gt;D：剩余可用内存；&lt;/li&gt;
&lt;li&gt;E：已经使用的内存。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;点击Memory Monitor的Dump Java Heap，会生成一个.hprof文件，位于&lt;strong&gt;工程名/captures/&lt;/strong&gt;文件夹下。AndroidStudio会自动使用HeapViewer打开。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96%E5%AE%9E%E6%88%98/hprof.jpg&quot; alt=&quot;Hprof Viewer打开.hprof文件&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;左面板说明：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Total Count 该类的实例个数&lt;/li&gt;
&lt;li&gt;Heap Count 选定的Heap中实例的个数&lt;/li&gt;
&lt;li&gt;Sizeof 每个实例占用的内存大小&lt;/li&gt;
&lt;li&gt;Shallow Size 所有该类的实例占用的内存大小&lt;/li&gt;
&lt;li&gt;Retained Size 该类的所有实例可支配的内存大小&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;右面板说明：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Instance 该类的所有实例对象（左侧Total Count为15，此处就有15个对象）&lt;/li&gt;
&lt;li&gt;Depth 深度, GC Root点到该实例的最短链路数&lt;/li&gt;
&lt;li&gt;Dominating Size 该实例可支配的内存大小&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;此处可以看出MainActivity存在了15个示例对象，怀疑此处有问题。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;附：Android Device Monitor抓取：（可忽略，直接跳过）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1. 首先打开AS中的Android Device Monitor工具 ，Tools—&amp;gt;Android—&amp;gt;Android Device Monitor,打开如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96%E5%AE%9E%E6%88%98/adm.png&quot; alt=&quot;Android Device Monitor&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2. 先选中你要检测的应用的包名，然后点击下图画圈的地方，会在程序包名后标记一个图标 &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96%E5%AE%9E%E6%88%98/click.png&quot; alt=&quot;点击一下&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3. 接下来要做的就是操作我们的app 。 之后点击下图的图标 就可导出hprof文件进行分析了&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96%E5%AE%9E%E6%88%98/export.png&quot; alt=&quot;导出&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;MAT&quot;&gt;&lt;a href=&quot;#MAT&quot; class=&quot;headerlink&quot; title=&quot;MAT&quot;&gt;&lt;/a&gt;MAT&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上述只是可以粗略的看出是不是有问题，而要知道问题出在哪里就需要借助MAT了。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;打开MAT工具 ，如果没有 可以在下面网址下载 ：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;a href=&quot;https://www.eclipse.org/mat/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;MAT工具下载地址&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96%E5%AE%9E%E6%88%98/matdownload.png&quot; alt=&quot;打开MAT&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;打开我们先前导出的hprof文件 ，不出意外会报下面的错误 :&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96%E5%AE%9E%E6%88%98/error.png&quot; alt=&quot;错误&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这是因为MAT是用来分析&lt;code&gt;Java&lt;/code&gt;程序的hprof文件的 与Android导出的hprof有一定的格式区别，因此我们需要把导出的hprof文件转换一下，sdk中提供给我们转换的工具 hprof-conv.exe 在下图的位置 &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96%E5%AE%9E%E6%88%98/conv.png&quot; alt=&quot;转换&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们看到adb.exe和hprof-conv.exe在同一个目录，这就比较幸运了，因为我们一般都会把adb路径加入环境变量，所以这个hprof-conv也会位于环境变量当中，因此我们不用cd进入这个目录去敲命令了，直接随便哪个控制台路径都可以。比如我们利用AS自带的Terminal。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;将生成的.hprof文件进行转换&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;格式转换命令：hprof-conv 原文件路径 转换后文件路径&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96%E5%AE%9E%E6%88%98/terminal.png&quot; alt=&quot;转换命令&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后用MAT打开转换后的.hprof文件&lt;br&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96%E5%AE%9E%E6%88%98/matshow.jpg&quot; alt=&quot;MAT打开.hprof&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;注意下面的Actions：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Histogram可以列出内存中每个对象的名字、数量以及大小。&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dominator Tree会将所有内存中的对象按大小进行排序，并且我们可以分析对象之间的引用结构。&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;一般使用最多的也是这两个功能。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Retained Heap表示这个对象以及它所持有的其它引用（包括直接和间接）所占的总内存&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;使用Histogram：&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;点击Histogram并在顶部的Regex中输入MainActivity会进行正则匹配，会将包含“MainActivity”的所有对象全部列出了出来，其中第一行就是MainActivity的实例。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96%E5%AE%9E%E6%88%98/histogram.jpg&quot; alt=&quot;Histogram&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对着想查看的对象点击右键 -&amp;gt; List objects -&amp;gt; with incoming references 查看具体MainActivity实例。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96%E5%AE%9E%E6%88%98/reference.jpg&quot; alt=&quot;reference&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对想要查看的对象实例点击右键-&amp;gt; Path To Gc Roots -&amp;gt; exclude weak reference（排除掉软引用）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96%E5%AE%9E%E6%88%98/noweak.jpg&quot; alt=&quot;noweak&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;注意：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;this$0前面的图标的左下角有个圆圈，这代表这个引用可以被Gc Roots引用到，由于MainActivity$LeakClass能被GC Roots访问到导致其不能被回收，从而它所持有的其它引用也无法被回收了，包括MainActivity，也包括MainActivity中所包含的其它资源。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;此时我们就找到了内存泄漏的原因。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;使用Dominator Tree&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96%E5%AE%9E%E6%88%98/dominator.jpg&quot; alt=&quot;dominator&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;使用上面Histogram的操作方式也可以找到泄漏的具体原因，此处不再累述。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;注意：&lt;strong&gt;每个对象前的图标的圆圈，并不代表一定是导致内存泄漏的原因，有些对象就是需要在内存中存活的，需要区别对待。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;LeakCanary&quot;&gt;&lt;a href=&quot;#LeakCanary&quot; class=&quot;headerlink&quot; title=&quot;LeakCanary&quot;&gt;&lt;/a&gt;LeakCanary&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;a href=&quot;https://github.com/square/leakcanary&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;LeakCanary&lt;/a&gt;是square出品的一个检测内存泄漏的库，集成到App之后便无需关心，在发生内存泄漏之后会Toast、通知栏弹出等方式提示，可以指出泄漏的引用路径，而且可以抓取当前的堆栈信息供详细分析。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96%E5%AE%9E%E6%88%98/leakcanary.jpg&quot; alt=&quot;LeakCanary&quot;&gt;&lt;/p&gt;
&lt;h1 id=&quot;Out-Of-Memory&quot;&gt;&lt;a href=&quot;#Out-Of-Memory&quot; class=&quot;headerlink&quot; title=&quot;Out Of Memory&quot;&gt;&lt;/a&gt;Out Of Memory&lt;/h1&gt;&lt;h2 id=&quot;Android-OOM&quot;&gt;&lt;a href=&quot;#Android-OOM&quot; class=&quot;headerlink&quot; title=&quot;Android OOM&quot;&gt;&lt;/a&gt;Android OOM&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Android系统的每个进程都有一个最大内存限制，如果申请的内存资源超过这个限制，系统就会抛出OOM错误。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Android 2.x系统，当dalvik allocated + external allocated + 新分配的大小 &amp;gt;= dalvik heap 最大值时候就会发生OOM。其中bitmap是放于external中 。&lt;/li&gt;
&lt;li&gt;Android 4.x系统，废除了external的计数器，类似bitmap的分配改到dalvik的java heap中申请，只要allocated + 新分配的内存 &amp;gt;= dalvik heap 最大值的时候就会发生OOM（art运行环境的统计规则还是和dalvik保持一致）&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;内存溢出是程序运行到某一阶段的最终结果，直接原因是剩余的内存不能满足内存的申请，但是再分析间接原因内存为什么没有了：&lt;/li&gt;
&lt;li&gt;内存泄漏的存在可能导致可用内存越来越少；&lt;/li&gt;
&lt;li&gt;内存申请的峰值超过了系统时间点剩余的内存；(例如：某手机单个进程可用最大内存为192M，目前分配内存80M，此时申请5M内存，但是当前时间点整个系统可用内存只有3M，此时没有超出单个进程可用最大内存，但是OOM也会发生)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;Avoid-Android-OOM&quot;&gt;&lt;a href=&quot;#Avoid-Android-OOM&quot; class=&quot;headerlink&quot; title=&quot;Avoid Android OOM&quot;&gt;&lt;/a&gt;Avoid Android OOM&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;除了避免内存泄漏之外，根据《Manage Your App’s Memory》，我们可以对内存的状态进行监听，在Activity中覆写此方法，根据不同的case进行不同的处理：&lt;br&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;@Override&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;onTrimMemory&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; level)&lt;/span&gt; &lt;/span&gt;&amp;#123;        &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;super&lt;/span&gt;.onTrimMemory(level);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TRIM_MEMORY_RUNNING_MODERATE：&lt;/strong&gt;你的应用正在运行并且不会被列为可杀死的。但是设备此时正运行于低内存状态下，系统开始触发杀死LRU Cache中的Process的机制。&lt;br&gt;&lt;strong&gt;TRIM_MEMORY_RUNNING_LOW：&lt;/strong&gt;你的应用正在运行且没有被列为可杀死的。但是设备正运行于更低内存的状态下，你应该释放不用的资源用来提升系统性能。&lt;br&gt;&lt;strong&gt;TRIM_MEMORY_RUNNING_CRITICAL：&lt;/strong&gt;你的应用仍在运行，但是系统已经把LRU Cache中的大多数进程都已经杀死，因此你应该立即释放所有非必须的资源。如果系统不能回收到足够的RAM数量，系统将会清除所有的LRU缓存中的进程，并且开始杀死那些之前被认为不应该杀死的进程，例如那个包含了一个运行态Service的进程。&lt;br&gt;当应用进程退到后台正在被Cached的时候，可能会接收到从onTrimMemory()中返回的下面的值之一：&lt;br&gt;&lt;strong&gt;TRIM_MEMORY_BACKGROUND：&lt;/strong&gt; 系统正运行于低内存状态并且你的进程正处于LRU缓存名单中最不容易杀掉的位置。尽管你的应用进程并不是处于被杀掉的高危险状态，系统可能已经开始杀掉LRU缓存中的其他进程了。你应该释放那些容易恢复的资源，以便于你的进程可以保留下来，这样当用户回退到你的应用的时候才能够迅速恢复。&lt;br&gt;&lt;strong&gt;TRIM_MEMORY_MODERATE：&lt;/strong&gt;系统正运行于低内存状态并且你的进程已经已经接近LRU名单的中部位置。如果系统开始变得更加内存紧张，你的进程是有可能被杀死的。&lt;br&gt;&lt;strong&gt;TRIM_MEMORY_COMPLETE：&lt;/strong&gt;系统正运行于低内存的状态并且你的进程正处于LRU名单中最容易被杀掉的位置。你应该释放任何不影响你的应用恢复状态的资源。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&quot;Memory-Churn&quot;&gt;&lt;a href=&quot;#Memory-Churn&quot; class=&quot;headerlink&quot; title=&quot;Memory Churn&quot;&gt;&lt;/a&gt;Memory Churn&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;Memory Churn内存抖动：大量的对象被创建又在短时间内马上被释放。&lt;/strong&gt;&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;瞬间产生大量的对象会严重占用Young Generation的内存区域，当达到阀值，剩余空间不够的时候，也会触发GC。&lt;strong&gt;系统花费在GC上的时间越多，进行界面绘制或流音频处理的时间就越短。&lt;/strong&gt;即使每次分配的对象占用了很少的内存，但是他们叠加在一起会增加Heap的压力，从而触发更多其他类型的GC。这个操作有可能会影响到帧率，并使得用户感知到性能问题。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96%E5%AE%9E%E6%88%98/memchurn.jpg&quot; alt=&quot;Drop Frame Occur&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;常见的可能引发内存抖动的情形：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;循环中创建临时对象；&lt;/li&gt;
&lt;li&gt;onDraw中创建Paint或Bitmap对象等；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;例如之前使用过的有些下拉刷新控件的实现方式，在onDraw中创建Bitmap等多个临时大对象会导致内存抖动。&lt;/p&gt;
&lt;h1 id=&quot;Bitmap&quot;&gt;&lt;a href=&quot;#Bitmap&quot; class=&quot;headerlink&quot; title=&quot;Bitmap&quot;&gt;&lt;/a&gt;Bitmap&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Bitmap的处理也是Android中的一个难点，当然使用第三方框架的话就屏蔽掉了这个难点。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Bitmap的内存模型；&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bitmap的加载、压缩、缓存等策略；&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;版本的兼容等；&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;关于Bitmap之后会写专门的一篇文章来介绍，此处可以参考《Handling Bitmaps》。也可以查看我之前的一片文章：&lt;a href=&quot;http://windrunnerlihuan.com/2016/07/12/%E6%B5%85%E6%9E%90Bitmap%E5%8D%A0%E6%8D%AE%E5%86%85%E5%AD%98%E5%A4%A7%E5%B0%8F/&quot;&gt;浅析Bitmap占据内存大小&lt;/a&gt;。&lt;/p&gt;
&lt;h1 id=&quot;Program-Advice&quot;&gt;&lt;a href=&quot;#Program-Advice&quot; class=&quot;headerlink&quot; title=&quot;Program Advice&quot;&gt;&lt;/a&gt;Program Advice&lt;/h1&gt;&lt;h2 id=&quot;节制地使用Service&quot;&gt;&lt;a href=&quot;#节制地使用Service&quot; class=&quot;headerlink&quot; title=&quot;节制地使用Service&quot;&gt;&lt;/a&gt;节制地使用Service&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;内存管理最大的错误之一就是让Service一直运行。在后台使用service时，除非它需要被触发并执行一个任务，否则其他时候Service都应该是停止状态。另外需要注意Service工作完毕之后需要被停止，以免造成内存泄漏。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;系统会倾向于保留有Service所在的进程，这使得进程的运行代价很高，&lt;strong&gt;因为系统没有办法把Service所占用的RAM空间腾出来让给其他组件，另外Service还不能被Paged out&lt;/strong&gt;。这减少了系统能够存放到LRU缓存当中的进程数量，它会影响应用之间的切换效率，甚至会导致系统内存使用不稳定，从而无法继续保持住所有目前正在运行的service。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;建议使用JobScheduler，而尽量避免使用持久性的Service。还有建议使用IntentService，它会在处理完交代给它的任务之后尽快结束自己。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;使用优化过的集合&quot;&gt;&lt;a href=&quot;#使用优化过的集合&quot; class=&quot;headerlink&quot; title=&quot;使用优化过的集合&quot;&gt;&lt;/a&gt;使用优化过的集合&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;Android API当中提供了一些优化过后的数据集合工具类，如SparseArray，SparseBooleanArray，以及LongSparseArray等，使用这些API可以让我们的程序更加高效。&lt;/strong&gt;传统Java API中提供的HashMap工具类会相对比较低效，因为它需要为每一个键值对都提供一个对象入口，而SparseArray就避免掉了基本数据类型转换成对象数据类型的时间。&lt;/p&gt;
&lt;h2 id=&quot;谨慎对待面向抽象&quot;&gt;&lt;a href=&quot;#谨慎对待面向抽象&quot; class=&quot;headerlink&quot; title=&quot;谨慎对待面向抽象&quot;&gt;&lt;/a&gt;谨慎对待面向抽象&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;开发者经常把抽象作为好的编程实践，因为抽象能够提升代码的灵活性与可维护性。然而，抽象会导致一个显著的开销：&lt;strong&gt;面向抽象需要额外的代码（不会被执行到），同样会被咨映射到内存中，耗费了更多的时间以及内存空间。因此如果面向抽象对你的代码没有显著的收益，那你应该避免使用&lt;/strong&gt;。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;例如：&lt;strong&gt;使用枚举通常会比使用静态常量要消耗两倍以上的内存，在Android开发当中我们应当尽可能地不使用枚举&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id=&quot;使用nano-protobufs序列化数据&quot;&gt;&lt;a href=&quot;#使用nano-protobufs序列化数据&quot; class=&quot;headerlink&quot; title=&quot;使用nano protobufs序列化数据&quot;&gt;&lt;/a&gt;使用nano protobufs序列化数据&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Protocol buffers是Google为序列化数据设计的一种语言无关、平台无关、具有良好扩展性的数据描述语言，与XML类似，但是更加轻量、快速、简单。如果使用protobufs来实现数据的序列化及反序列化，&lt;strong&gt;建议在客户端使用nano protobufs，因为通常的protobufs会生成冗余代码，会导致可用内存减少，Apk体积变大，运行速度减慢。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;避免内存抖动&quot;&gt;&lt;a href=&quot;#避免内存抖动&quot; class=&quot;headerlink&quot; title=&quot;避免内存抖动&quot;&gt;&lt;/a&gt;避免内存抖动&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;垃圾回收通常不会影响应用的表现，但是短时间内多次的垃圾回收会消耗掉界面绘制的时间。系统花费在GC上的时间越多，进行界面绘制或流音频处理的时间就越短&lt;/strong&gt;。通常内存抖动会导致多次的GC，实践中内存抖动代表了一段时间内分配了临时对象。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;例如：在For循环中分配了多个临时对象，或在onDraw()方法中创建了Paint、Bitmap对象，应用产生了大量的对象；这会很快耗尽young generation的可用内存，导致GC发生。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;使用Analyze your RAM usage中的工具找出代码里内存抖动的地方。考虑把操作移出内部循环，或者将其移动到基于工厂的分配结构中。&lt;/p&gt;
&lt;h2 id=&quot;移除消耗内存的库、缩减Apk的大小&quot;&gt;&lt;a href=&quot;#移除消耗内存的库、缩减Apk的大小&quot; class=&quot;headerlink&quot; title=&quot;移除消耗内存的库、缩减Apk的大小&quot;&gt;&lt;/a&gt;移除消耗内存的库、缩减Apk的大小&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;查看Apk的大小，包括三方库和内嵌的资源，这些都会影响应用消耗的内存。通过减少冗余、非必须或大的组件、库、图片、资源、动画等，都可以改善应用的内存消耗。&lt;/p&gt;
&lt;h2 id=&quot;使用Dagger-2进行依赖注入&quot;&gt;&lt;a href=&quot;#使用Dagger-2进行依赖注入&quot; class=&quot;headerlink&quot; title=&quot;使用Dagger 2进行依赖注入&quot;&gt;&lt;/a&gt;使用Dagger 2进行依赖注入&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果您打算在应用程序中使用依赖注入框架，请考虑使用Dagger 2。 Dagger不使用反射来扫描应用程序的代码。 &lt;strong&gt;Dagger的编译时注解技术实现意味着它不需要不必要的运行时成本。而使用反射的其它依赖注入框架通常通过扫描代码来初始化过程。 此过程可能需要显着更多的CPU周期和RAM，并可能导致应用程序启动时明显的卡顿。&lt;/strong&gt;&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;备注：之前的文档是不建议使用依赖注入框架，因为实现原理是使用反射，而进化为编译时注解之后，就不再有反射带来的影响了。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;谨慎使用第三方库&quot;&gt;&lt;a href=&quot;#谨慎使用第三方库&quot; class=&quot;headerlink&quot; title=&quot;谨慎使用第三方库&quot;&gt;&lt;/a&gt;谨慎使用第三方库&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;很多开源的library代码都不是为移动端而编写的，如果运用在移动设备上，并不一定适合。&lt;strong&gt;即使是针对Android而设计的library，也需要特别谨慎，特别是在你不知道引入的library具体做了什么事情的时候&lt;/strong&gt;。例如，其中一个library使用的是nano protobufs, 而另外一个使用的是micro protobufs。这样一来，在你的应用里面就有2种protobuf的实现方式。这样类似的冲突还可能发生在输出日志，加载图片，缓存等等模块里面。&lt;strong&gt;另外不要为了1个或者2个功能而导入整个library，如果没有一个合适的库与你的需求相吻合，你应该考虑自己去实现，而不是导入一个大而全的解决方案&lt;/strong&gt;。&lt;/p&gt;
&lt;h1 id=&quot;Other&quot;&gt;&lt;a href=&quot;#Other&quot; class=&quot;headerlink&quot; title=&quot;Other&quot;&gt;&lt;/a&gt;Other&lt;/h1&gt;&lt;h2 id=&quot;谨慎使用LargeHeap属性&quot;&gt;&lt;a href=&quot;#谨慎使用LargeHeap属性&quot; class=&quot;headerlink&quot; title=&quot;谨慎使用LargeHeap属性&quot;&gt;&lt;/a&gt;谨慎使用LargeHeap属性&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;可以通过在manifest的application标签下添加largeHeap=true的属性来为应用声明一个更大的heap空间(可以通过getLargeMemoryClass()来获取到这个更大的heap size阈值)。然而，&lt;strong&gt;声明得到更大Heap阈值的本意是为了一小部分会消耗大量RAM的应用(例如一个大图片的编辑应用)。不要轻易的因为你需要使用更多的内存而去请求一个大的Heap Size&lt;/strong&gt;。只有当你清楚的知道哪里会使用大量的内存并且知道为什么这些内存必须被保留时才去使用large heap，&lt;strong&gt;使用额外的内存空间会影响系统整体的用户体验，并且会使得每次gc的运行时间更长。在任务切换时，系统的性能会大打折扣&lt;/strong&gt;。另外, large heap并不一定能够获取到更大的heap。在某些有严格限制的机器上，large heap的大小和通常的heap size是一样的。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;谨慎使用多进程&quot;&gt;&lt;a href=&quot;#谨慎使用多进程&quot; class=&quot;headerlink&quot; title=&quot;谨慎使用多进程&quot;&gt;&lt;/a&gt;谨慎使用多进程&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;多进程确实是一种可以帮助我们节省和管理内存的高级技巧。&lt;strong&gt;如果你要使用它的话一定要谨慎使用，因为绝大多数的应用程序都不应该在多个进程当中运行的，一旦使用不当，它甚至会增加额外的内存而不是帮我们节省内存；同时需要知晓多进程带来的缺点&lt;/strong&gt;。这个技巧比较适用于那些需要在后台去完成一项独立的任务，和前台的功能是可以完全区分开的场景。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里举一个比较适合去使用多进程技巧的场景，比如说我们正在做一个音乐播放器软件，其中播放音乐的功能应该是一个独立的功能，它不需要和UI方面有任何关系，即使软件已经关闭了也应该可以正常播放音乐。如果此时我们只使用一个进程，那么即使用户关闭了软件，已经完全由Service来控制音乐播放了，系统仍然会将许多UI方面的内存进行保留。在这种场景下就非常适合使用两个进程，一个用于UI展示，另一个则用于在后台持续地播放音乐。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;实现方式可能存在的问题：例如启动页闪屏图，show完毕之后应该释放掉Bitmap。&quot;&gt;&lt;a href=&quot;#实现方式可能存在的问题：例如启动页闪屏图，show完毕之后应该释放掉Bitmap。&quot; class=&quot;headerlink&quot; title=&quot;实现方式可能存在的问题：例如启动页闪屏图，show完毕之后应该释放掉Bitmap。&quot;&gt;&lt;/a&gt;实现方式可能存在的问题：例如启动页闪屏图，show完毕之后应该释放掉Bitmap。&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;一些实现方式看起来没有问题实现了功能但是实际上可能对内存造成了影响。我在使用Heap Viewer查看Bitmap对象时发现了一张只需下载不应该被加载的图。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96%E5%AE%9E%E6%88%98/other1.jpg&quot; alt=&quot;HeapViewer查找Bitmap&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;使用HeapViewer可直接查看Bitmap&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96%E5%AE%9E%E6%88%98/other2.jpg&quot; alt=&quot;HeapViewer直接查看图片&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;内存中出现的不应该被加载的图&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;通过查阅代码，发现问题出在：此处下载图片作为另一个模块的使用图，但是下载的方法竟然是使用图片加载器加载出来Bitmap然后再保存到本地；而且保存之后也没有将Bitmap对象释放掉。&lt;/strong&gt;&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;与之类似的还有：首页闪屏图展示之后，Bitmap对象应该及时释放掉。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;使用try-catch进行捕获&quot;&gt;&lt;a href=&quot;#使用try-catch进行捕获&quot; class=&quot;headerlink&quot; title=&quot;使用try catch进行捕获&quot;&gt;&lt;/a&gt;使用try catch进行捕获&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;对高风险OOM代码块如展示高清大图等进行try catch，在catch块加载非高清的图片并做相应内存回收的处理。注意OOM是OutOfMemoryError，不能使用Exception进行捕获。&lt;/strong&gt;&lt;/p&gt;
&lt;h1 id=&quot;Summary&quot;&gt;&lt;a href=&quot;#Summary&quot; class=&quot;headerlink&quot; title=&quot;Summary&quot;&gt;&lt;/a&gt;Summary&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;内存优化的套路：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1. &lt;strong&gt;解决所有的内存泄漏&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;集成LeakCanary，可以方便的定位出90%的内存泄漏问题；&lt;/li&gt;
&lt;li&gt;通过反复进出可疑界面，观察内存增减的情况，Dump Java Heap获取当前堆栈信息使用MAT进行分析。&lt;/li&gt;
&lt;li&gt;内存泄漏的常见情形可参照《Android 内存泄漏分析心得》&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2. &lt;strong&gt;避免内存抖动&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;避免在循环中创建临时对象；&lt;/li&gt;
&lt;li&gt;避免在onDraw中创建Paint、Bitmap对象等。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3. &lt;strong&gt;Bitmap的使用&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用三方库加载图片一般不会出内存问题，但是需要注意图片使用完毕的释放，而不是被动等待释放。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4. &lt;strong&gt;使用优化过的数据结构&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;5. &lt;strong&gt;使用onTrimMemory根据不同的内存状态做相应处理&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;6. &lt;strong&gt;Library的使用&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;去掉无用的Library，对生成的Apk进行反编译查看使用到的Library，避免出现无用的Lib仍然被打进Apk；&lt;/li&gt;
&lt;li&gt;避免引入巨大的Library；&lt;/li&gt;
&lt;li&gt;使用Proguard进行混淆、压缩。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;参考：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/playlist?list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Android性能优化典范&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://android.xsoftlab.net/training/articles/memory.html&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Manage Your App’s Memory&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;小结&quot;&gt;&lt;a href=&quot;#小结&quot; class=&quot;headerlink&quot; title=&quot;小结&quot;&gt;&lt;/a&gt;小结&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;最近还是很忙，主要是生活上有多多事情需要处理，所以没空闲时间更新博客了，唉。。。。。。本篇没有妹子，见谅~~&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;事情依旧很多，生活的、工作的，成长总是需要代价的。一直憧憬童年和大学，那是两种异曲同工的生活态度。假装自己是个孩子，一直不想长大，被自己小小的愿望襁褓着，不去理会外面世界的沧海桑田。白驹过隙，岁月在脸上留下了痕迹，不再隐瞒早已不年轻的事实。伴随着时光点滴流逝，心也在渐渐老去。也许成长就是一种淡然吧，从锋芒毕露到心如止水，从棱角分明到不露声色。少了昔日偶尔破釜沉舟的勇气，更多的是经常瞻前顾后的思虑。时光荏苒，没有留下刻骨铭心的记忆，更多的是平淡、安静。我渐渐喜欢这种感觉，岁月静好，没有跌宕起伏的生活剧情，没有扣人心弦的情景环节，一切安好，便是生活最美好的恩赐。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;记忆渐渐模糊，没有留下印记。没有选择性忘记，但却真实在一点一点消逝。那些旧照片也没能留下，早已不见了踪影，那些故人，都逐渐失去了联系，那些雨天泥泞的小路，还有路边在儿时植树节时新栽的小树，也都变得那么陌生。只有那些花儿，却开的愈加鲜艳茂密。就像一颗顽强的心，一颗不服输的心，在抗拒随波逐流的人生。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;多年之前，我们都还是个孩子。经过岁月的洗礼，也许会变得更加沉稳，也会变得更加冷静，亦或者是……冷漠。回忆往昔，这一路走来，还是渐渐变成了孩时最讨厌的自己，一个冷漠的自己，一个绝情的自己。安静也许是一个借口，一种掩饰，透过镜子，终于看清了真实的自己，那个自私的自己。有人说，社会会逼着一个人成长，是啊，虽然不愿承认，但是至少褪去了青年时怕事嫌烦表选出来的虚伪，获得更多的是学会了处事不惊的态度，和勇于承担责任的勇气。如果选择对生活妥协，是不会答应的，即使没了追梦赤子心，至少还有追逐本心的动力。不忘初心，坚持自己的初衷。青春即使如同《老男孩》的歌词唱的那样：”青春如同奔流的江河,一去不回来不及道别,只剩下麻木的我,没有了当年的热血……”即便如此，依然要做不一样的我，一个不退缩、不妥协的我，一个默默前行的我，一个坚持本心的我————“我就是我，是颜色不一样的烟火，天空海阔，要做最坚强的泡沫，我喜欢我，让蔷薇开出一种结果，孤独的沙漠里一样盛放的赤裸裸”&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这次带来一篇性能优化的文章，内容来自&lt;code&gt;APP架构师&lt;/code&gt;,我稍微修改了一些部分，加了一些内容。&lt;/p&gt;
    
    </summary>
    
      <category term="Android技术点" scheme="http://windrunnerlihuan.com/categories/Android%E6%8A%80%E6%9C%AF%E7%82%B9/"/>
    
    
      <category term="性能优化" scheme="http://windrunnerlihuan.com/tags/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/"/>
    
  </entry>
  
  <entry>
    <title>Android SurfaceFlinger 学习之路(一)----Android图形显示之HAL层Gralloc模块实现</title>
    <link href="http://windrunnerlihuan.com/2017/03/12/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E4%B8%80-Android%E5%9B%BE%E5%BD%A2%E6%98%BE%E7%A4%BA%E4%B9%8BHAL%E5%B1%82Gralloc%E6%A8%A1%E5%9D%97%E5%AE%9E%E7%8E%B0/"/>
    <id>http://windrunnerlihuan.com/2017/03/12/Android-SurfaceFlinger-学习之路-一-Android图形显示之HAL层Gralloc模块实现/</id>
    <published>2017-03-12T12:10:11.000Z</published>
    <updated>2019-01-06T07:27:29.969Z</updated>
    
    <content type="html">&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;好久没更新了，主要是因为年前和年后太忙了，尤其是年后这一段时间，忙得把身体都忙坏了。。。。。。终于在我GG之前，提交了离职，总算赢得了一些空闲时间，赶紧养养身体。。。现在处于即将待业状态，正好有时间研究一下年前就想了解的surfaceflinger模块。。。不过最近我也看了下，surfaceflinger内容太多太复杂了，&lt;code&gt;也许这个系列我坚持不了多久&lt;/code&gt;，不能像上一个MediaPlayer系列那样。。。。。。&lt;code&gt;同时，因为目前我处于即将待业状况，所以求好心HR或者大牛带我入新坑，感激不尽(~ToT~)&lt;/code&gt;&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;下载内核代码-准备工作&quot;&gt;&lt;a href=&quot;#下载内核代码-准备工作&quot; class=&quot;headerlink&quot; title=&quot;下载内核代码(准备工作)&quot;&gt;&lt;/a&gt;下载内核代码(准备工作)&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;因为接下来分析需要用到部分kernel代码，所有我们需要先把kernel代码下载下来。&lt;/p&gt;
&lt;h2 id=&quot;更换hosts文件&quot;&gt;&lt;a href=&quot;#更换hosts文件&quot; class=&quot;headerlink&quot; title=&quot;更换hosts文件&quot;&gt;&lt;/a&gt;更换hosts文件&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;因为天朝&lt;code&gt;GFW&lt;/code&gt;的原因，所以不能直接访问google放置android source code的网站 &lt;a href=&quot;https://source.android.com/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;https://source.android.com/&lt;/a&gt; 。这个上面有很详细的教程，教大家下载、编译源码，和其他变动相关的知识。所以我们需要&lt;strong&gt;Fan Qiang&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果买了VPN的土豪；找到免费vpn（GreenVPN、FreeVPN、hideVPN、rssVPN等等，好多都失效了）；还有可以去&lt;strong&gt;亚马逊&lt;/strong&gt;申请一个免费服务器（一年），可以搭建自己的FQ服务器（这个需要绑定一张VISA信用卡，银联的不行），&lt;a href=&quot;http://images.windrunnerlihuan.com/file/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%B8%80%29----Android%E5%9B%BE%E5%BD%A2%E6%98%BE%E7%A4%BA%E4%B9%8BHAL%E5%B1%82Gralloc%E6%A8%A1%E5%9D%97%E5%AE%9E%E7%8E%B0/AWS%E8%AF%A6%E7%BB%86FQ%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%90%AD%E5%BB%BA.doc&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;这里&lt;/a&gt; 有个教程，我上传到了自己博客服务器，大家可以下载下来；或者有稳定且流量大的FQ软件（比如赛风、自由门、蓝灯、畅游无限浏览器、影梭等）；或者有靠谱的hosts文件的，可以跳过这一步。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;因为要拉kernel代码，文件比较大，所以我推荐更换hosts文件。这里推荐&lt;code&gt;老D&lt;/code&gt; hosts，地址是 &lt;a href=&quot;https://laod.cn/hosts/2017-google-hosts.html&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;https://laod.cn/hosts/2017-google-hosts.html&lt;/a&gt; 。都是傻瓜式教程，应该都会。&lt;/p&gt;
&lt;h2 id=&quot;下载kernel代码&quot;&gt;&lt;a href=&quot;#下载kernel代码&quot; class=&quot;headerlink&quot; title=&quot;下载kernel代码&quot;&gt;&lt;/a&gt;下载kernel代码&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;更换完hosts文件后，进入android源码官网，然后找到里面的&lt;strong&gt;Explore the Source&lt;/strong&gt;标题下面描述里面的&lt;strong&gt;AOSP repository&lt;/strong&gt;，点击进入源码仓库 &lt;a href=&quot;https://android.googlesource.com/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;https://android.googlesource.com/&lt;/a&gt; 。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1) 因为我们要下kernel源码，所以选择&lt;strong&gt;kenrnel/common&lt;/strong&gt;,下载这一个通用代码；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2) 用git下载代码：git clone &lt;a href=&quot;https://android.googlesource.com/kernel/common&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;https://android.googlesource.com/kernel/common&lt;/a&gt; ；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3) 切换分支，我选了一个release版本：android-4.4-n-release，所以要git checkout -b android-4.4-n-release remotes/origin/android-4.4-n-release，然后pull一下，common文件夹下就有代码了。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4) 最后将下载好的代码导入source insight，这一步就不用细说了。&lt;/p&gt;
&lt;h1 id=&quot;初识Gralloc模块&quot;&gt;&lt;a href=&quot;#初识Gralloc模块&quot; class=&quot;headerlink&quot; title=&quot;初识Gralloc模块&quot;&gt;&lt;/a&gt;初识Gralloc模块&lt;/h1&gt;&lt;h2 id=&quot;Gralloc模块简介&quot;&gt;&lt;a href=&quot;#Gralloc模块简介&quot; class=&quot;headerlink&quot; title=&quot;Gralloc模块简介&quot;&gt;&lt;/a&gt;Gralloc模块简介&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Android设备的显示屏被抽象为一个帧缓冲区，而Android系统中的SurfaceFlinger服务就是通过向这个帧缓冲区写入内容来绘制应用程序的用户界面的。Android系统在硬件抽象层中提供了一个Gralloc模块，封装了对帧缓冲区的所有访问操作。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Linux内核在启动的过程中会创建一个类别和名称分别为“graphics”和“fb0”的设备，用来描述系统中的第一个帧缓冲区，即第一个显示屏，其中，数字0表示从设备号。注意，系统中至少要存在一个显示屏，因此，名称为“fb0”的设备是肯定会存在的，否则的话，就是出错了。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;init进程在启动的过程中，会启动另外一个进程ueventd来管理系统的设备文件。当ueventd进程启动起来之后，会通过netlink接口来Linux内核通信，以便可以获得内核中的硬件设备变化通知。而当ueventd进程发现内核中创建了一个类型和名称分别为“graphics”和“fb0”的设备的时候，就会这个设备创建一个/dev/graphics/fb0设备文件。这样，用户空间的应用程序就可以通过设备文件/dev/graphics/fb0来访问内核中的帧缓冲区，即在设备的显示屏中绘制指定的画面。注意，用户空间的应用程序一般是通过内存映射的方式来访问设备文件/dev/graphics/fb0的。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Android系统在硬件抽象层中提供了一个Gralloc模块，封装了对帧缓冲区的所有访问操作。用户空间的应用程序在使用帧缓冲区之间，首先要加载Gralloc模块，并且获得一个gralloc设备和一个fb设备。有了gralloc设备之后，用户空间中的应用程序就可以申请分配一块图形缓冲区，并且将这块图形缓冲区映射到应用程序的地址空间来，以便可以向里面写入要绘制的画面的内容。最后，用户空间中的应用程序就通过fb设备来将已经准备好了的图形缓冲区渲染到帧缓冲区中去，即将图形缓冲区的内容绘制到显示屏中去。相应地，当用户空间中的应用程序不再需要使用一块图形缓冲区的时候，就可以通过gralloc设备来释放它，并且将它从地址空间中解除映射。&lt;/p&gt;
&lt;h2 id=&quot;代码结构&quot;&gt;&lt;a href=&quot;#代码结构&quot; class=&quot;headerlink&quot; title=&quot;代码结构&quot;&gt;&lt;/a&gt;代码结构&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Gralloc模块实现源码位于：hardware/libhardware/modules/gralloc ：&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;|——– Android.mk&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;|——– framebuffer.cpp&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;|——– gralloc.cpp&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;|——– gralloc_priv.h&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;|——– gr.h&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;|——– mapper.cpp&lt;/p&gt;
&lt;h1 id=&quot;功能分析&quot;&gt;&lt;a href=&quot;#功能分析&quot; class=&quot;headerlink&quot; title=&quot;功能分析&quot;&gt;&lt;/a&gt;功能分析&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接下来，我们就按照上述使用情景来分析Gralloc模块的实现。&lt;/p&gt;
&lt;h2 id=&quot;Gralloc模块的加载过程&quot;&gt;&lt;a href=&quot;#Gralloc模块的加载过程&quot; class=&quot;headerlink&quot; title=&quot;Gralloc模块的加载过程&quot;&gt;&lt;/a&gt;Gralloc模块的加载过程&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;每一个HAL模块都有一个ID值，以这些ID值为参数来调用硬件抽象层提供的函数&lt;strong&gt;hw_get_module&lt;/strong&gt;就可以将指定的模块加载到内存来，并且获得一个&lt;strong&gt;hw_module_t&lt;/strong&gt;接口来打开相应的设备。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Gralloc模块的ID值定义在hardware/libhardware/include/hardware/gralloc.h文件中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/**&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * The id of this module&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;define&lt;/span&gt; GRALLOC_HARDWARE_MODULE_ID &lt;span class=&quot;string&quot;&gt;&quot;gralloc&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数&lt;strong&gt;hw_get_module&lt;/strong&gt;实现在hardware/libhardware/hardware.c文件中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;hw_get_module&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; *id, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;hw_module_t&lt;/span&gt; **module)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; hw_get_module_by_class(id, &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;, module);&lt;span class=&quot;comment&quot;&gt;//调用hw_get_module_by_class函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//hw_get_module_by_class函数实现&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;hw_get_module_by_class&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; *class_id, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; *inst,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                           &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;hw_module_t&lt;/span&gt; **module)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; i;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; prop[PATH_MAX];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; path[PATH_MAX];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; name[PATH_MAX]; &lt;span class=&quot;comment&quot;&gt;//PATH_MAX为256&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; prop_name[PATH_MAX];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (inst)&lt;span class=&quot;comment&quot;&gt;//NULL&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;built_in&quot;&gt;snprintf&lt;/span&gt;(name, PATH_MAX, &lt;span class=&quot;string&quot;&gt;&quot;%s.%s&quot;&lt;/span&gt;, class_id, inst);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        strlcpy(name, class_id, PATH_MAX);&lt;span class=&quot;comment&quot;&gt;//字符串拷贝&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * Here we rely on the fact that calling dlopen multiple times on&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * the same .so will simply increment a refcount (and not load&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * a new copy of the library).&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * We also assume that dlopen() is thread-safe.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     &lt;span class=&quot;comment&quot;&gt;//我们依赖的事实是，调用dlopen方法多次打开相同的so库会简单的增加引用计数(而不会重复加载多次库的拷贝)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     &lt;span class=&quot;comment&quot;&gt;//我们认为dlopen方法是线程安全的&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* First try a property specific to the class and possibly instance */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//先查找确定系统属性的值是否为空&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;built_in&quot;&gt;snprintf&lt;/span&gt;(prop_name, &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(prop_name), &lt;span class=&quot;string&quot;&gt;&quot;ro.hardware.%s&quot;&lt;/span&gt;, name);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (property_get(prop_name, prop, &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果不为空，则找到属性对应的so库是否存在&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hw_module_exists(path, &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(path), name, prop) == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;goto&lt;/span&gt; found;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* Loop through the configuration variants looking for a module */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果上面没找到指定的so库，则循环遍历指定数组里的属性，然后找到第一个存在的so并跳出&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; i&amp;lt;HAL_VARIANT_KEYS_COUNT; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (property_get(variant_keys[i], prop, &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hw_module_exists(path, &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(path), name, prop) == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;goto&lt;/span&gt; found;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* Nothing found, try the default */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果第二步查找也没找到，就用默认的default属性&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hw_module_exists(path, &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(path), name, &lt;span class=&quot;string&quot;&gt;&quot;default&quot;&lt;/span&gt;) == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;goto&lt;/span&gt; found;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -ENOENT;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;found:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* load the module, if this fails, we&#39;re doomed, and we should not try&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * to load a different variant. */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果我们找到了相关so，则加载它&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; load(class_id, path, module);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/**&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * There are a set of variant filename for modules. The form of the filename&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * is &quot;&amp;lt;MODULE_ID&amp;gt;.variant.so&quot; so for the led module the Dream variants &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * of base &quot;ro.product.board&quot;, &quot;ro.board.platform&quot; and &quot;ro.arch&quot; would be:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; *&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * led.trout.so&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * led.msm7k.so&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * led.ARMV6.so&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * led.default.so&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; *variant_keys[] = &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;string&quot;&gt;&quot;ro.hardware&quot;&lt;/span&gt;,  &lt;span class=&quot;comment&quot;&gt;/* This goes first so that it can pick up a different&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                       file on the emulator. */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;string&quot;&gt;&quot;ro.product.board&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;string&quot;&gt;&quot;ro.board.platform&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;string&quot;&gt;&quot;ro.arch&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面流程我们分步来看：&lt;/p&gt;
&lt;h3 id=&quot;查询对应动态库&quot;&gt;&lt;a href=&quot;#查询对应动态库&quot; class=&quot;headerlink&quot; title=&quot;查询对应动态库&quot;&gt;&lt;/a&gt;查询对应动态库&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）先查找确定系统属性的值是否为空，property_get函数到系统属性，可以在shell环境下用getprop ro.hardware.%s找到ro.hardware.%s属性，最后一个字符串自己指定；然后调用hw_module_exists函数顺着&lt;strong&gt;/system/lib/hw和/vendor/lib/hw或者/system/lib64/hw和/vendor/lib64/hw&lt;/strong&gt;查找相应so库是否存在，我们看看hw_module_exists函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * Check if a HAL with given name and subname exists, if so return 0, otherwise&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * otherwise return negative.  On success path will contain the path to the HAL.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;comment&quot;&gt;//检查HAL层给的文件名是否存在，如果存在返回0，否则返回负无穷&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;comment&quot;&gt;//如果成功了，会把这个路径包含进HAL&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;hw_module_exists&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; *path, &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; path_len, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; *name,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; *subname)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;built_in&quot;&gt;snprintf&lt;/span&gt;(path, path_len, &lt;span class=&quot;string&quot;&gt;&quot;%s/%s.%s.so&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             HAL_LIBRARY_PATH2, name, subname);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (access(path, R_OK) == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;built_in&quot;&gt;snprintf&lt;/span&gt;(path, path_len, &lt;span class=&quot;string&quot;&gt;&quot;%s/%s.%s.so&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             HAL_LIBRARY_PATH1, name, subname);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (access(path, R_OK) == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -ENOENT;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/** Base path of the hal modules */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//主要在下面目录下找相关so库&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; defined(__LP64__)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;define&lt;/span&gt; HAL_LIBRARY_PATH1 &lt;span class=&quot;string&quot;&gt;&quot;/system/lib64/hw&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;define&lt;/span&gt; HAL_LIBRARY_PATH2 &lt;span class=&quot;string&quot;&gt;&quot;/vendor/lib64/hw&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;else&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;define&lt;/span&gt; HAL_LIBRARY_PATH1 &lt;span class=&quot;string&quot;&gt;&quot;/system/lib/hw&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;define&lt;/span&gt; HAL_LIBRARY_PATH2 &lt;span class=&quot;string&quot;&gt;&quot;/vendor/lib/hw&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）如果第一步GG了，就进入第二步，则循环遍历指定数组里的属性，然后找到第一个存在的so并跳出。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数hw_get_module依次在目录/system/lib/hw和/vendor/lib/hw中(或64位对应目录)查找一个名称为”&lt;module_id&gt;.variant.so”的文件，其中，&amp;lt; MODULE_ID &amp;gt;是一个模块ID，而variant表示”ro.hardware”、”ro.product.board”、”ro.board.platform”和”ro.arch”四个系统属性值之一。例如，对于Gralloc模块来说，函数hw_get_module依次在目录/system/lib/hw和/vendor/lib/hw中检查是否存在以下四个文件：&lt;/module_id&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;gralloc.&amp;lt; ro.hardware &amp;gt;.so&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;gralloc.&amp;lt; ro.product.board &amp;gt;.so&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;gralloc.&amp;lt; ro.board.platform &amp;gt;.so&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;gralloc.&amp;lt; ro.arch &amp;gt;.so&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;只要其中的一个文件存在，  函数hw_get_module就会停止查找过程，并且调用另外一个函数load来将这个文件加载到内存中来。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）如果第二步也GG了，就进入第三步，如果第二步查找也没找到，就用默认的default属性。如果在/system/lib/hw和/vendor/lib/hw中均不存这些文件，那么函数hw_get_module就会在目录/system/lib/hw中查找是否存在一个名称为&lt;strong&gt;gralloc.default.so&lt;/strong&gt;的文件。如果存在的话，那么也会调用函数load将它加载到内存中来。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）找到对应的so库后，就要调用&lt;strong&gt;load&lt;/strong&gt;函数将他加载到内存中。&lt;/p&gt;
&lt;h3 id=&quot;加载对应动态库&quot;&gt;&lt;a href=&quot;#加载对应动态库&quot; class=&quot;headerlink&quot; title=&quot;加载对应动态库&quot;&gt;&lt;/a&gt;加载对应动态库&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数load也是实现在文件hardware/libhardware/hardware.c文件中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/**&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * Load the file defined by the variant and if successful&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * return the dlopen handle and the hmi.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * @return 0 = success, !0 = failure.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; *id,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; *path,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;hw_module_t&lt;/span&gt; **pHmi)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; status;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; *handle;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;hw_module_t&lt;/span&gt; *hmi;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * load the symbols resolving undefined symbols before&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * dlopen returns. Since RTLD_GLOBAL is not or&#39;d in with&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * RTLD_NOW the external symbols will not be global&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    handle = dlopen(path, RTLD_NOW);&lt;span class=&quot;comment&quot;&gt;//用dlopen函数将对应so库加载到内存中&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (handle == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; *err_str = dlerror();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;load: module=%s\n%s&quot;&lt;/span&gt;, path, err_str?err_str:&lt;span class=&quot;string&quot;&gt;&quot;unknown&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        status = -EINVAL;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;goto&lt;/span&gt; done;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* Get the address of the struct hal_module_info. */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//调用函数dlsym来获得它所导出的符号HMI&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; *sym = HAL_MODULE_INFO_SYM_AS_STR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    hmi = (&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;hw_module_t&lt;/span&gt; *)dlsym(handle, sym);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hmi == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;load: couldn&#39;t find symbol %s&quot;&lt;/span&gt;, sym);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        status = -EINVAL;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;goto&lt;/span&gt; done;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* Check that the id matches */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//检查id是否匹配&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;built_in&quot;&gt;strcmp&lt;/span&gt;(id, hmi-&amp;gt;id) != &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGE(&lt;span class=&quot;string&quot;&gt;&quot;load: id=%s != hmi-&amp;gt;id=%s&quot;&lt;/span&gt;, id, hmi-&amp;gt;id);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        status = -EINVAL;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;goto&lt;/span&gt; done;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    hmi-&amp;gt;dso = handle;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* success */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    status = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    done:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (status != &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        hmi = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (handle != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            dlclose(handle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            handle = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGV(&lt;span class=&quot;string&quot;&gt;&quot;loaded HAL id=%s path=%s hmi=%p handle=%p&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                id, path, *pHmi, handle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    *pHmi = hmi;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; status;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在Linux系统中，后缀名为”so”的文件为动态链接库文件，可能通过函数dlopen来加载到内存中。硬件抽象层模块编写规范规定每一个硬件抽象层模块都必须导出一个符号名称为&lt;strong&gt;HAL_MODULE_INFO_SYM_AS_STR&lt;/strong&gt;的符号，而且这个符号必须是用来描述一个类型为&lt;strong&gt;hw_module_t&lt;/strong&gt;的结构体的。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;HAL_MODULE_INFO_SYM_AS_STR&lt;/strong&gt;是一个宏，定义在文件hardware/libhardware/include/hardware/hardware.h文件中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/**&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * Name of the hal_module_info as a string&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;define&lt;/span&gt; HAL_MODULE_INFO_SYM_AS_STR  &lt;span class=&quot;string&quot;&gt;&quot;HMI&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;将Gralloc模块加载到内存中来之后，就可以调用函数dlsym来获得它所导出的符号&lt;strong&gt;HMI&lt;/strong&gt;。由于这个符号指向的是一个&lt;strong&gt;hw_module_t&lt;/strong&gt;结构体，因此，最后函数load就可以强制地将这个符号转换为一个hw_module_t结构体指针，并且保存在输出参数pHmi中返回给调用者。调用者获得了这个hw_module_t结构体指针之后，就可以创建一个gralloc设备或者一个fb设备。&lt;/p&gt;
&lt;h3 id=&quot;数据结构定义&quot;&gt;&lt;a href=&quot;#数据结构定义&quot; class=&quot;headerlink&quot; title=&quot;数据结构定义&quot;&gt;&lt;/a&gt;数据结构定义&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;模块Gralloc实现在目录hardware/libhardware/modules/gralloc中，它导出的符号&lt;strong&gt;HMI&lt;/strong&gt;定义在文件hardware/libhardware/modules/gralloc/gralloc.cpp文件中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;hw_module_methods_t&lt;/span&gt; gralloc_module_methods = &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        .open = gralloc_device_open&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;private_module_t&lt;/span&gt; HAL_MODULE_INFO_SYM = &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    .base = &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        .common = &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            .tag = HARDWARE_MODULE_TAG,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            .version_major = &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            .version_minor = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            .id = GRALLOC_HARDWARE_MODULE_ID,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            .name = &lt;span class=&quot;string&quot;&gt;&quot;Graphics Memory Allocator Module&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            .author = &lt;span class=&quot;string&quot;&gt;&quot;The Android Open Source Project&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            .methods = &amp;amp;gralloc_module_methods&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        .registerBuffer = gralloc_register_buffer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        .unregisterBuffer = gralloc_unregister_buffer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        .lock = gralloc_lock,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        .unlock = gralloc_unlock,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    .framebuffer = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    .flags = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    .numBuffers = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    .bufferMask = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    .lock = PTHREAD_MUTEX_INITIALIZER,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    .currentBuffer = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;HAL_MODULE_INFO_SYM&lt;/strong&gt;也是一个宏，它的值是与宏HAL_MODULE_INFO_SYM_AS_STR对应的，它也是定义在文件hardware/libhardware/include/hardware/hardware.h文件中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/**&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * Name of the hal_module_info&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;define&lt;/span&gt; HAL_MODULE_INFO_SYM         HMI&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;符号&lt;strong&gt;HAL_MODULE_INFO_SYM&lt;/strong&gt;的类型为&lt;strong&gt;private_module_t&lt;/strong&gt;。前面提到，符号HAL_MODULE_INFO_SYM必须指向一个&lt;strong&gt;hw_module_t&lt;/strong&gt;结构体，但是这里它指向的却是一个private_module_t结构体，是不是有问题呢？为了弄清楚这个问题，我们首先了解一下结构体private_module_t的定义，如下图：&lt;br&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%B8%80%29----Android%E5%9B%BE%E5%BD%A2%E6%98%BE%E7%A4%BA%E4%B9%8BHAL%E5%B1%82Gralloc%E6%A8%A1%E5%9D%97%E5%AE%9E%E7%8E%B0/jicheng.jpg&quot; alt=&quot;继承关系&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;结构体&lt;strong&gt;private_module_t&lt;/strong&gt;的第一个成员变量&lt;strong&gt;base&lt;/strong&gt;指向一个&lt;strong&gt;gralloc_module_t&lt;/strong&gt;结构体，而gralloc_module_t结构体的第一个成员变量&lt;strong&gt;common&lt;/strong&gt;又指向了一个&lt;strong&gt;hw_module_t&lt;/strong&gt;结构体，这意味着，指向一个private_module_t结构体的指针同时可以用作一个gralloc_module_t或者hw_module_t结构体提针来使用。&lt;code&gt;事实上，这是使用C语言来实现的一种继承关系&lt;/code&gt;，等价于结构体private_module_t继承结构体gralloc_module_t，而结构体gralloc_module_t继承hw_module_t结构体。这样，&lt;strong&gt;我们就可以把在Gralloc模块中定义的符号HAL_MODULE_INFO_SYM看作是一个hw_module_t结构体&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;hw_module_t&lt;/strong&gt;结构体有一个重要的成员变量&lt;strong&gt;methods&lt;/strong&gt;，它的类型为&lt;strong&gt;hw_module_methods_t&lt;/strong&gt;，它用来描述一个HAL模块的操作方法列表。结构体hw_module_methods_t只定义有一个操作方法open，用来打开一个指定的设备。在Gralloc模块中，用来打开指定设备的函数被指定为gralloc_device_open，通过这个函数就可以打开Gralloc模块中的gralloc或者fb设备，后面我们再详细分析。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）结构体&lt;strong&gt;gralloc_module_t&lt;/strong&gt;定义在文件hardware/libhardware/include/hardware/gralloc.h中，它主要是定义了四个用来操作图形缓冲区的成员函数，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt; &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;　　&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;hw_module_t&lt;/span&gt; common;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;　　&lt;span class=&quot;comment&quot;&gt;//映射一块图形缓冲区到一个进程的地址空间去  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;　　&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*registerBuffer)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* module,&lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt; handle);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;　　&lt;span class=&quot;comment&quot;&gt;//取消映射一块图形缓冲区到一个进程的地址空间去  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;　　&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*unregisterBuffer)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* module,&lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt; handle);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;　　&lt;span class=&quot;comment&quot;&gt;//锁定一个指定的图形缓冲区  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*lock)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* module,&lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt; handle, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; usage,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; l, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; t, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; h,&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;** vaddr);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//解锁一个指定的图形缓冲区  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;　　&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*unlock)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* module,&lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt; handle);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*perform)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* module,&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; operation, ... );  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;* reserved_proc[&lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;];  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125; &lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;成员函数registerBuffer和unregisterBuffer分别用来注册和注销一个指定的图形缓冲区，这个指定的图形缓冲区使用一个buffer_handle_t句柄来描述。所谓注册图形缓冲区，实际上就是将一块图形缓冲区映射到一个进程的地址空间去，而注销图形缓冲区就是执行相反的操作。&lt;/li&gt;
&lt;li&gt;成员函数lock和unlock分别用来锁定和解锁一个指定的图形缓冲区，这个指定的图形缓冲区同样是使用一个buffer_handle_t句柄来描述。在访问一块图形缓冲区的时候，例如，向一块图形缓冲写入内容的时候，需要将该图形缓冲区锁定，用来避免访问冲突。在锁定一块图形缓冲区的时候，可以指定要锁定的图形绘冲区的位置以及大小，这是通过参数l、t、w和h来指定的，其中，参数l和t指定的是要访问的图形缓冲区的左上角位置，而参数w和h指定的是要访问的图形缓冲区的宽度和长度。锁定之后，就可以获得由参数参数l、t、w和h所圈定的一块缓冲区的起始地址，保存在输出参数vaddr中。另一方面，在访问完成一块图形缓冲区之后，需要解除这块图形缓冲区的锁定。&lt;/li&gt;
&lt;li&gt;在Gralloc模块中，符号HAL_MODULE_INFO_SYM指向的gralloc结构体的成员函数registerBuffer、unregisterBuffer、lock和unlock分别被指定为函数gralloc_register_buffer、gralloc_unregister_buffer、gralloc_lock和gralloc_unlock，后面我们再详细分析它们的实现。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）结构体&lt;strong&gt;private_module_t&lt;/strong&gt;定义在文件hardware/libhardware/modules/gralloc/gralloc_priv.h中，它主要是用来描述帧缓冲区的属性，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;private_module_t&lt;/span&gt; &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt; base;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;* framebuffer; &lt;span class=&quot;comment&quot;&gt;//指向系统帧缓冲区的句柄  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags; &lt;span class=&quot;comment&quot;&gt;//用来标志系统帧缓冲区是否支持双缓冲  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; numBuffers;&lt;span class=&quot;comment&quot;&gt;//表示系统帧缓冲区包含有多少个图形缓冲区  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; bufferMask; &lt;span class=&quot;comment&quot;&gt;//记录系统帧缓冲区中的图形缓冲区的使用情况  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;pthread_mutex_t&lt;/span&gt; lock; &lt;span class=&quot;comment&quot;&gt;//一个互斥锁，用来保护结构体private_module_t的并行访问  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt; currentBuffer; &lt;span class=&quot;comment&quot;&gt;//用来描述当前正在被渲染的图形缓冲区  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; pmem_master;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;* pmem_master_base;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; fb_var_screeninfo info; &lt;span class=&quot;comment&quot;&gt;//保存设备显示屏的动态属性信息  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; fb_fix_screeninfo finfo; &lt;span class=&quot;comment&quot;&gt;////保存设备显示屏的固定属性信息  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;float&lt;/span&gt; xdpi; &lt;span class=&quot;comment&quot;&gt;//描述设备显示屏在宽度  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;float&lt;/span&gt; ydpi; &lt;span class=&quot;comment&quot;&gt;//描述设备显示屏在高度  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;float&lt;/span&gt; fps; &lt;span class=&quot;comment&quot;&gt;//用来描述显示屏的刷新频率  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;成员变量framebuffer的类型为private_handle_t，它是一个指向系统帧缓冲区的句柄，后面我们再分析结构体private_handle_t的定义。&lt;/li&gt;
&lt;li&gt;成员变量flags用来标志系统帧缓冲区是否支持双缓冲。如果支持的话，那么它的PAGE_FLIP位就等于1，否则的话，就等于0。&lt;/li&gt;
&lt;li&gt;成员变量numBuffers表示系统帧缓冲区包含有多少个图形缓冲区。一个帧缓冲区包含有多少个图形缓冲区是与它的可视分辨率以及虚拟分辨率的大小有关的。例如，如果一个帧缓冲区的可视分辨率为800 x 600，而虚拟分辨率为1600 x 600，那么这个帧缓冲区就可以包含有两个图形缓冲区。&lt;/li&gt;
&lt;li&gt;成员变量bufferMask用来记录系统帧缓冲区中的图形缓冲区的使用情况。例如，假设系统帧缓冲区有两个图形缓冲区，这时候成员变量bufferMask就有四种取值，分别是二进制的00、01、10和11，其中，00分别表示两个图缓冲区都是空闲的，01表示第1个图形缓冲区已经分配出去，而第2个图形缓冲区是空闲的，10表示第1个图形缓冲区是空闲的，而第2个图形缓冲区已经分配出去，11表示两个图缓冲区都已经分配出去。&lt;/li&gt;
&lt;li&gt;成员变量lock是一个互斥锁，用来保护结构体private_module_t的并行访问。&lt;/li&gt;
&lt;li&gt;成员变量&lt;strong&gt;currentBuffer&lt;/strong&gt;的类型为&lt;strong&gt;buffer_handle_t&lt;/strong&gt;，用来描述当前正在被渲染的图形缓冲区，后面我们再分析它的定义。&lt;/li&gt;
&lt;li&gt;成员变量pmem_master和pmem_master_base目前没有使用。&lt;/li&gt;
&lt;li&gt;成员变量info和finfo的类型分别为fb_var_screeninfo和fb_fix_screeninfo，它们用来保存设备显示屏的属性信息，其中，成员变量info保存的属性信息是可以动态设置的，而成员变量finfo保存的属性信息是只读的。这两个成员变量的值可以通过IO控制命令FBIOGET_VSCREENINFO和FBIOGET_FSCREENINFO来从帧缓冲区驱动模块中获得。&lt;/li&gt;
&lt;li&gt;成员变量xdpi和ydpi分别用来描述设备显示屏在宽度和高度上的密度，即每英寸有多少个像素点。&lt;/li&gt;
&lt;li&gt;&lt;p&gt;成员变量fps用来描述显示屏的刷新频率，它的单位的fps，即每秒帧数。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）接下来， 我们再分析结构体&lt;strong&gt;buffer_handle_t&lt;/strong&gt;的定义。结构体buffer_handle_t定义在文件hardware/libhardware/include/hardware/gralloc.h文件中，如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; native_handle* &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;它是一个类型为&lt;strong&gt;native_handle_t&lt;/strong&gt;的指针，而结构体native_handle_t用来描述一个本地句柄值，它定义在系统运行时层的文件system/core/include/cutils/native_handle.h文件中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; native_handle  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; version; &lt;span class=&quot;comment&quot;&gt;//设置为结构体native_handle_t的大小，用来标识结构体native_handle_t的版本  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; numFds;  &lt;span class=&quot;comment&quot;&gt;//表示结构体native_handle_t所包含的文件描述符的个数，这些文件描述符保存在成员变量data所指向的一块缓冲区中。  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; numInts; &lt;span class=&quot;comment&quot;&gt;//表示结构体native_handle_t所包含的整数值的个数，这些整数保存在成员变量data所指向的一块缓冲区中。  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; data[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]; &lt;span class=&quot;comment&quot;&gt;//指向的一块缓冲区中  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125; &lt;span class=&quot;keyword&quot;&gt;native_handle_t&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;成员变量version的大小被设置为结构体native_handle_t的大小，用来标识结构体native_handle_t的版本。&lt;/li&gt;
&lt;li&gt;成员变量numFds和numInts表示结构体native_handle_t所包含的文件描述符以及整数值的个数，这些文件描述符和整数保存在成员变量data所指向的一块缓冲区中。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）我们一般不直接使用native_handle_t结构体来描述一个本地句柄值，而是通过它的子类来描述一个具体的本地句柄值。接下来我们就通过结构体private_handle_t的定义来说明native_handle_t结构体的用法。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;结构体&lt;strong&gt;private_handle_t&lt;/strong&gt;用来描述一块图形缓冲区，这块图形缓冲区可能是在帧缓冲区中分配的，也可能是在内存中分配的，视具体情况而定，它定义在文件hardware/libhardware/modules/gralloc/gralloc_priv.h文件中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;ifdef&lt;/span&gt; __cplusplus  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt; : &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; native_handle &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;else&lt;/span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt; &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; native_handle nativeHandle;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;enum&lt;/span&gt; &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        PRIV_FLAGS_FRAMEBUFFER = &lt;span class=&quot;number&quot;&gt;0x00000001&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// file-descriptors  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;     fd;  &lt;span class=&quot;comment&quot;&gt;////指向一个文件描述符，这个文件描述符要么指向帧缓冲区设备，要么指向一块匿名共享内存 &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// ints  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;     magic;  &lt;span class=&quot;comment&quot;&gt;//指向一个魔数，它的值由静态成员变量sMagic来指定，用来标识一个private_handle_t结构&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;     flags;  &lt;span class=&quot;comment&quot;&gt;//用来描述一个缓冲区的标志，它的值要么等于0，要么等于PRIV_FLAGS_FRAMEBUFFER  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;     size;   &lt;span class=&quot;comment&quot;&gt;//用来描述一个缓冲区的大小。 &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;     offset; &lt;span class=&quot;comment&quot;&gt;//用来描述一个缓冲区的偏移地址。&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;FIXME:&lt;/span&gt; the attributes below should be out-of-line  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;     base;  &lt;span class=&quot;comment&quot;&gt;//用来描述一个缓冲区的实际地址，它是通过成员变量offset来计算得到的。 &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;     pid;   &lt;span class=&quot;comment&quot;&gt;//用来描述一个缓冲区的创建者的PID。  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;ifdef&lt;/span&gt; __cplusplus  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; sNumInts = &lt;span class=&quot;number&quot;&gt;6&lt;/span&gt;;  &lt;span class=&quot;comment&quot;&gt;//包含有6个整数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; sNumFds = &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;;   &lt;span class=&quot;comment&quot;&gt;//包含有1个文件描述符 &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; sMagic = &lt;span class=&quot;number&quot;&gt;0x3141592&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; fd, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; size, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; flags) :  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        fd(fd), magic(sMagic), flags(flags), size(size), offset(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        base(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;), pid(getpid())  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        version = &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(native_handle);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        numInts = sNumInts;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        numFds = sNumFds;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ~&lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;() &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        magic = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;validate&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; native_handle* h)&lt;/span&gt; &lt;/span&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;* hnd = (&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;*)h;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!h || h-&amp;gt;version != &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(native_handle) ||  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                h-&amp;gt;numInts != sNumInts || h-&amp;gt;numFds != sNumFds ||  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                hnd-&amp;gt;magic != sMagic)  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            LOGE(&lt;span class=&quot;string&quot;&gt;&quot;invalid gralloc handle (at %p)&quot;&lt;/span&gt;, h);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -EINVAL;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;为了方便描述，我们假设我们是在C++环境中编译文件gralloc_priv.h，即编译环境定义有宏__cplusplus。这样，结构体private_handle_t就是从结构体native_handle_t继承下来的，它包含有1个文件描述符以及6个整数，以及三个静态成员变量。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;成员变量fd指向一个文件描述符，这个文件描述符要么指向帧缓冲区设备，要么指向一块匿名共享内存，取决于它的宿主结构体private_handle_t描述的一个图形缓冲区是在帧缓冲区分配的，还是在内存中分配的。&lt;/li&gt;
&lt;li&gt;成员变量magic指向一个魔数，它的值由静态成员变量sMagic来指定，用来标识一个private_handle_t结构体。&lt;/li&gt;
&lt;li&gt;成员变量flags用来描述一个图形缓冲区的标志，它的值要么等于0，要么等于PRIV_FLAGS_FRAMEBUFFER。当一个图形缓冲区的标志值等于PRIV_FLAGS_FRAMEBUFFER的时候，就表示它是在帧缓冲区中分配的。&lt;/li&gt;
&lt;li&gt;成员变量size用来描述一个图形缓冲区的大小。&lt;/li&gt;
&lt;li&gt;成员变量offset用来描述一个图形缓冲区的偏移地址。例如，当一个图形缓冲区是在一块内存中分块的时候，假设这块内存的地址为start，那么这个图形缓冲区的起始地址就为start + offset。&lt;/li&gt;
&lt;li&gt;成员变量base用来描述一个图形缓冲区的实际地址，它是通过成员变量offset来计算得到的。例如，上面计算得到的start + offset的值就保存在成员变量base中。&lt;/li&gt;
&lt;li&gt;成员变量pid用来描述一个图形缓冲区的创建者的PID。例如，如果一个图形缓冲区是在ID值为1000的进程中创建的，那么用来描述这个图形缓冲区的private_handle_t结构体的成员变量pid的值就等于1000。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;结构体private_handle_t的静态成员变量sMagic前面已经描述过了，另外两个静态成员变量sNumInts和sNumFds的值分别等于1和6，表示结构体private_handle_t包含有1个文件描述符和6个整数，它们是用来初始化结构体private_handle_t的父类native_handle_t的成员变量numInts和numFds的，如结构体private_handle_t的构造函数所示。从这里就可以看出，结构体private_handle_t的父类native_handle_t的成员变量data所指向的缓冲区就是由结构体private_handle_t的成员变量fds、magic、flags、size、offset、base和pid所占用的连续内存块来组成的，一共包含有7个整数。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;结构体private_handle_t还定义了一个静态成员函数validate，用来验证一个native_handle_t指针是否指向了一个private_handle_t结构体。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%B8%80%29----Android%E5%9B%BE%E5%BD%A2%E6%98%BE%E7%A4%BA%E4%B9%8BHAL%E5%B1%82Gralloc%E6%A8%A1%E5%9D%97%E5%AE%9E%E7%8E%B0/leitu.png&quot; alt=&quot;数据结构图&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;至此，Gralloc模块的加载过程以及相关的数据结构体就介绍到这里，接下来我们分别分析定义在Gralloc模块中的gralloc和fb设备的打开过程。&lt;/p&gt;
&lt;h2 id=&quot;Gralloc设备的打开过程&quot;&gt;&lt;a href=&quot;#Gralloc设备的打开过程&quot; class=&quot;headerlink&quot; title=&quot;Gralloc设备的打开过程&quot;&gt;&lt;/a&gt;Gralloc设备的打开过程&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在Gralloc模块中，gralloc设备的ID值定义为&lt;strong&gt;GRALLOC_HARDWARE_GPU0&lt;/strong&gt;。GRALLOC_HARDWARE_GPU0是一个宏，定义在文件hardware/libhardware/include/hardware/gralloc.h中， 如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/**&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * Name of the graphics device to open&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;define&lt;/span&gt; GRALLOC_HARDWARE_GPU0 &lt;span class=&quot;string&quot;&gt;&quot;gpu0&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;gralloc设备使用结构体&lt;strong&gt;alloc_device_t&lt;/strong&gt; 来描述。结构体alloc_device_t有两个成员函数&lt;strong&gt;alloc&lt;/strong&gt;和&lt;strong&gt;free&lt;/strong&gt;，分别用来分配和释放图形缓冲区。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;结构体alloc_device_t 也是定义在文件hardware/libhardware/include/hardware/gralloc.h中， 如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;alloc_device_t&lt;/span&gt; &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;hw_device_t&lt;/span&gt; common;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*alloc)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;alloc_device_t&lt;/span&gt;* dev,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; h, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; format, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; usage,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt;* handle, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;* stride);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*&lt;span class=&quot;built_in&quot;&gt;free&lt;/span&gt;)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;alloc_device_t&lt;/span&gt;* dev,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt; handle);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125; &lt;span class=&quot;keyword&quot;&gt;alloc_device_t&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Gralloc模块在在文件hardware/libhardware/include/hardware/gralloc.h中定义了一个帮助函数gralloc_open，用来打开gralloc设备，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/** convenience API for opening and closing a supported device */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;inline&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;gralloc_open&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;hw_module_t&lt;/span&gt;* module, &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;alloc_device_t&lt;/span&gt;** device)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; module-&amp;gt;methods-&amp;gt;open(module, &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            GRALLOC_HARDWARE_GPU0, (&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;hw_device_t&lt;/span&gt;**)device);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;参数&lt;strong&gt;module&lt;/strong&gt;指向的是一个用来描述Gralloc模块的&lt;strong&gt;hw_module_t&lt;/strong&gt;结构体，它的成员变量&lt;strong&gt;methods&lt;/strong&gt;所指向的一个&lt;strong&gt;hw_module_methods_t&lt;/strong&gt;结构体的成员函数&lt;strong&gt;open&lt;/strong&gt;指向了Gralloc模块中的函数&lt;strong&gt;gralloc_device_open&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数&lt;strong&gt;gralloc_device_open&lt;/strong&gt;定义在文件hardware/libhardware/modules/gralloc/gralloc.cpp文件中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;gralloc_context_t&lt;/span&gt; &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;alloc_device_t&lt;/span&gt;  device;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* our private data here */&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;......  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;gralloc_device_open&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;hw_module_t&lt;/span&gt;* module, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt;* name,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;hw_device_t&lt;/span&gt;** device)&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; status = -EINVAL;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!&lt;span class=&quot;built_in&quot;&gt;strcmp&lt;/span&gt;(name, GRALLOC_HARDWARE_GPU0)) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;gralloc_context_t&lt;/span&gt; *dev;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dev = (&lt;span class=&quot;keyword&quot;&gt;gralloc_context_t&lt;/span&gt;*)&lt;span class=&quot;built_in&quot;&gt;malloc&lt;/span&gt;(&lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(*dev));  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;/* initialize our state here */&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;built_in&quot;&gt;memset&lt;/span&gt;(dev, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(*dev));  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;/* initialize the procs */&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dev-&amp;gt;device.common.tag = HARDWARE_DEVICE_TAG;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dev-&amp;gt;device.common.version = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dev-&amp;gt;device.common.module = &lt;span class=&quot;keyword&quot;&gt;const_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;hw_module_t&lt;/span&gt;*&amp;gt;(module);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dev-&amp;gt;device.common.close = gralloc_close;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dev-&amp;gt;device.alloc   = gralloc_alloc;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dev-&amp;gt;device.&lt;span class=&quot;built_in&quot;&gt;free&lt;/span&gt;    = gralloc_free;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        *device = &amp;amp;dev-&amp;gt;device.common;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        status = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;   &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; status;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个函数主要是用来创建一个&lt;strong&gt;gralloc_context_t&lt;/strong&gt;结构体，并且对它的成员变量&lt;strong&gt;device&lt;/strong&gt;进行初始化。结构体gralloc_context_t的成员变量device的类型为&lt;strong&gt;gralloc_device_t&lt;/strong&gt;，它用来描述一个gralloc设备。前面提到，gralloc设备是用来分配和释放图形缓冲区的，这是通过调用它的成员函数alloc和free来实现的。从这里可以看出，函数gralloc_device_open所打开的gralloc设备的成员函数alloc和free分别被设置为Gralloc模块中的函数&lt;strong&gt;gralloc_alloc&lt;/strong&gt;和&lt;strong&gt;gralloc_free&lt;/strong&gt;，后面我们再详细分析它们的实现。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;至此，gralloc设备的打开过程就分析完成了，接下来我们继续分析fb设备的打开过程。&lt;/p&gt;
&lt;h2 id=&quot;fb设备的打开过程&quot;&gt;&lt;a href=&quot;#fb设备的打开过程&quot; class=&quot;headerlink&quot; title=&quot;fb设备的打开过程&quot;&gt;&lt;/a&gt;fb设备的打开过程&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在Gralloc模块中，fb设备的ID值定义为&lt;strong&gt;GRALLOC_HARDWARE_FB0&lt;/strong&gt;。GRALLOC_HARDWARE_FB0是一个宏，定义在文件hardware/libhardware/include/hardware/fb.h中， 如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;define&lt;/span&gt; GRALLOC_HARDWARE_FB0 &lt;span class=&quot;string&quot;&gt;&quot;fb0&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;fb设备使用结构体framebuffer_device_t 来描述。结构体framebuffer_device_t是用来描述系统帧缓冲区的信息，它定义在文件hardware/libhardware/include/hardware/fb.h中， 如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;framebuffer_device_t&lt;/span&gt; &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;hw_device_t&lt;/span&gt; common;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* flags describing some attributes of the framebuffer */&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;  flags;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* dimensions of the framebuffer in pixels */&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;  width;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;  height;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* frambuffer stride in pixels */&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;       stride;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* framebuffer pixel format */&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;       format;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* resolution of the framebuffer&#39;s display panel in pixel per inch*/&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;float&lt;/span&gt;     xdpi;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;float&lt;/span&gt;     ydpi;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* framebuffer&#39;s display panel refresh rate in frames per second */&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;float&lt;/span&gt;     fps;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* min swap interval supported by this framebuffer */&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;       minSwapInterval;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* max swap interval supported by this framebuffer */&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;       maxSwapInterval;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; reserved[&lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;];  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*setSwapInterval)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;framebuffer_device_t&lt;/span&gt;* window,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; interval);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*setUpdateRect)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;framebuffer_device_t&lt;/span&gt;* window,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; left, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; top, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; width, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; height);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*post)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;framebuffer_device_t&lt;/span&gt;* dev, &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt; buffer);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; (*compositionComplete)(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;framebuffer_device_t&lt;/span&gt;* dev);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;* reserved_proc[&lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;];  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125; &lt;span class=&quot;keyword&quot;&gt;framebuffer_device_t&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;成员变量flags用来记录系统帧缓冲区的标志，目前没有使用这成员变量，它的值被设置为0。&lt;/li&gt;
&lt;li&gt;成员变量width和height分别用来描述设备显示屏的宽度和高度，它们是以像素为单位的。&lt;/li&gt;
&lt;li&gt;成员变量stride用来描述设备显示屏的一行有多少个像素点。&lt;/li&gt;
&lt;li&gt;成员变量format用来描述系统帧缓冲区的像素格式，支持的像素格式主要有HAL_PIXEL_FORMAT_RGBX_8888和HAL_PIXEL_FORMAT_RGB_565两种。HAL_PIXEL_FORMAT_RGBX_8888表示一个像素使用32位来描述，R、G和B分别占8位，另外8位未使用。HAL_PIXEL_FORMAT_RGB_565表示一个像素使用16位来描述，R、G和B分别占5、6和5位。&lt;/li&gt;
&lt;li&gt;成员变量xdpi和ydpi分别用来描述设备显示屏在宽度和高度上的密度，即每英寸有多少个像素点。&lt;/li&gt;
&lt;li&gt;成员变量fps用来描述设备显示屏的刷新频率，它的单位是帧每秒。&lt;/li&gt;
&lt;li&gt;成员变量minSwapInterval和maxSwapInterval用来描述帧缓冲区交换前后两个图形缓冲区的最小和最大时间间隔。&lt;/li&gt;
&lt;li&gt;成员变量reserved是保留给将来使用的。&lt;/li&gt;
&lt;li&gt;成员函数setSwapInterval用来设置帧缓冲区交换前后两个图形缓冲区的最小和最大时间间隔。&lt;/li&gt;
&lt;li&gt;成员函数setUpdateRect用来设置帧缓冲区的更新区域。&lt;/li&gt;
&lt;li&gt;成员函数post用来将图形缓冲区buffer的内容渲染到帧缓冲区中去，即显示在设备的显示屏中去。&lt;/li&gt;
&lt;li&gt;成员函数compositionComplete用来通知fb设备device，图形缓冲区的组合工作已经完成，目前没有使用这个成员函数。&lt;/li&gt;
&lt;li&gt;成员变量reserved是一个函数指针数组，它们是保留给将来使用的。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在结构体framebuffer_device_t的一系列成员函数中，&lt;strong&gt;post&lt;/strong&gt;是最重要的一个成员函数，用户空间的应用程序通过调用这个成员函数就可以在设备的显示屏中渲染指定的画面，后面我们将详细讲这个函数的实现。&lt;/p&gt;
&lt;p&gt;Gralloc模块在在文件hardware/libhardware/include/hardware/fb.h中定义了一个帮助函数&lt;strong&gt;framebuffer_open&lt;/strong&gt;，用来打开fb设备，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/** convenience API for opening and closing a supported device */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;inline&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;framebuffer_open&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;hw_module_t&lt;/span&gt;* module,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;framebuffer_device_t&lt;/span&gt;** device)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; module-&amp;gt;methods-&amp;gt;open(module,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            GRALLOC_HARDWARE_FB0, (&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;hw_device_t&lt;/span&gt;**)device);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;参数module指向的是一个用来描述Gralloc模块的&lt;strong&gt;hw_module_t&lt;/strong&gt;结构体，前面提到，它的成员变量methods所指向的一个hw_module_methods_t结构体的成员函数open指向了Gralloc模块中的函数&lt;strong&gt;gralloc_device_open&lt;/strong&gt;，这个函数打开fb设备的代码段如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;gralloc_device_open&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;hw_module_t&lt;/span&gt;* module, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt;* name,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;hw_device_t&lt;/span&gt;** device)&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; status = -EINVAL;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!&lt;span class=&quot;built_in&quot;&gt;strcmp&lt;/span&gt;(name, GRALLOC_HARDWARE_GPU0)) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        status = fb_device_open(module, name, device);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; status;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;参数name的值等于&lt;strong&gt;GRALLOC_HARDWARE_FB0&lt;/strong&gt;，因此，函数gralloc_device_open接下来会调用另外一个函数&lt;strong&gt;fb_device_open&lt;/strong&gt;来执行打开fb设备的操作。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数&lt;strong&gt;fb_device_open&lt;/strong&gt;定义在文件hardware/libhardware/modules/gralloc/framebuffer.cpp中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;fb_context_t&lt;/span&gt; &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;framebuffer_device_t&lt;/span&gt;  device;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;......  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;fb_device_open&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;hw_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* module, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt;* name,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;hw_device_t&lt;/span&gt;** device)&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; status = -EINVAL; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//判断打开的是fb设备  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!&lt;span class=&quot;built_in&quot;&gt;strcmp&lt;/span&gt;(name, GRALLOC_HARDWARE_FB0)) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;alloc_device_t&lt;/span&gt;* gralloc_device;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//打开gpu设备 &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        status = gralloc_open(module, &amp;amp;gralloc_device);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (status &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; status;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;/* initialize our state here */&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//创建一个fb_context_t对象，用来描述fb设备上下文  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;fb_context_t&lt;/span&gt; *dev = (&lt;span class=&quot;keyword&quot;&gt;fb_context_t&lt;/span&gt;*)&lt;span class=&quot;built_in&quot;&gt;malloc&lt;/span&gt;(&lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(*dev));  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;built_in&quot;&gt;memset&lt;/span&gt;(dev, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(*dev));  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;/* initialize the procs */&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//初始化fb_context_t对象  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dev-&amp;gt;device.common.tag = HARDWARE_DEVICE_TAG;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dev-&amp;gt;device.common.version = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dev-&amp;gt;device.common.module = &lt;span class=&quot;keyword&quot;&gt;const_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;hw_module_t&lt;/span&gt;*&amp;gt;(module);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//注册fb设备的操作函数 &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dev-&amp;gt;device.common.close = fb_close;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dev-&amp;gt;device.setSwapInterval = fb_setSwapInterval;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dev-&amp;gt;device.post            = fb_post;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        dev-&amp;gt;device.setUpdateRect = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;private_module_t&lt;/span&gt;* m = (&lt;span class=&quot;keyword&quot;&gt;private_module_t&lt;/span&gt;*)module;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//将fb映射到当前进程地址空间 &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        status = mapFrameBuffer(m);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (status &amp;gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; stride = m-&amp;gt;finfo.line_length / (m-&amp;gt;info.bits_per_pixel &amp;gt;&amp;gt; &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; format = (m-&amp;gt;info.bits_per_pixel == &lt;span class=&quot;number&quot;&gt;32&lt;/span&gt;)  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                         ? HAL_PIXEL_FORMAT_RGBX_8888  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                         : HAL_PIXEL_FORMAT_RGB_565;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;ifdef&lt;/span&gt; NO_32BPP  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            format = HAL_PIXEL_FORMAT_RGB_565;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;&amp;amp;&amp;gt;(dev-&amp;gt;device.flags) = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;&amp;amp;&amp;gt;(dev-&amp;gt;device.width) = m-&amp;gt;info.xres;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt;&amp;amp;&amp;gt;(dev-&amp;gt;device.height) = m-&amp;gt;info.yres;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;&amp;amp;&amp;gt;(dev-&amp;gt;device.stride) = stride;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;&amp;amp;&amp;gt;(dev-&amp;gt;device.format) = format;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;float&lt;/span&gt;&amp;amp;&amp;gt;(dev-&amp;gt;device.xdpi) = m-&amp;gt;xdpi;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;float&lt;/span&gt;&amp;amp;&amp;gt;(dev-&amp;gt;device.ydpi) = m-&amp;gt;ydpi;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;float&lt;/span&gt;&amp;amp;&amp;gt;(dev-&amp;gt;device.fps) = m-&amp;gt;fps;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;&amp;amp;&amp;gt;(dev-&amp;gt;device.minSwapInterval) = &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;const_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;&amp;amp;&amp;gt;(dev-&amp;gt;device.maxSwapInterval) = &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            *device = &amp;amp;dev-&amp;gt;device.common;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; status;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）这个函数主要是用来创建一个&lt;strong&gt;fb_context_t&lt;/strong&gt;结构体，并且对它的成员变量&lt;strong&gt;device&lt;/strong&gt;进行初始化。结构体fb_context_t的成员变量device的类型为&lt;strong&gt;framebuffer_device_t&lt;/strong&gt;，前面提到，它是用来描述fb设备的。fb设备主要是用来渲染图形缓冲区的，这是通过调用它的成员函数post来实现的。从这里可以看出，函数fb_device_open所打开的fb设备的成员函数&lt;strong&gt;post&lt;/strong&gt;被设置为Gralloc模块中的函数&lt;strong&gt;fb_post&lt;/strong&gt;，后面我们再详细分析它的实现。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）函数fb_device_open在打开fb设备的过程中，会调用另外一个函数&lt;strong&gt;mapFrameBuffer&lt;/strong&gt;来获得系统帧缓冲区的信息，并且将这些信息保存在参数&lt;strong&gt;module&lt;/strong&gt;所描述的一个&lt;strong&gt;private_module_t&lt;/strong&gt;结构体的各个成员变量中。有了系统帧缓冲区的信息之后，函数fb_device_open接下来就可以对前面所打开的一个fb设备的各个成员变量进行初始化。这些成员变量的含义可以参考前面对结构体&lt;strong&gt;framebuffer_device_t&lt;/strong&gt;的介绍。接下来我们只简单介绍一下结构体framebuffer_device_t的成员变量&lt;strong&gt;stride&lt;/strong&gt;和&lt;strong&gt;format&lt;/strong&gt;的初始化过程。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）变量&lt;strong&gt;m&lt;/strong&gt;的成员变量&lt;strong&gt;finfo&lt;/strong&gt;的类型为&lt;strong&gt;fb_fix_screeninfo&lt;/strong&gt;，它是在函数mapFrameBuffer中被始化的。fb_fix_screeninfo是在内核中定义的一个结构体，&lt;strong&gt;用来描述设备显示屏的固定属性信息&lt;/strong&gt;，其中，它的成员变量&lt;strong&gt;line_length&lt;/strong&gt;用来描述显示屏一行像素总共所占用的字节数。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;变量m的另外一个成员变量&lt;strong&gt;info&lt;/strong&gt;的类型为&lt;strong&gt;fb_var_screeninfo&lt;/strong&gt;，它也是在函数mapFrameBuffer中被始化的。fb_var_screeninfo也是内核中定义的一个结构体，&lt;strong&gt;用来描述可以动态设置的显示屏属性信息&lt;/strong&gt;，其中，它的成员变量&lt;strong&gt;bits_per_pixel&lt;/strong&gt;用来描述显示屏每一个像素所占用的位数。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这样，我们将&lt;strong&gt;m-&amp;gt;info.bits_per_pixel&lt;/strong&gt;的值向右移3位，就可以得到显示屏每一个像素所占用的字节数。用显示屏每一个像素所占用的字节数去除显示屏一行像素总共所占用的字节数&lt;strong&gt;m-&amp;gt;finfo.line_length&lt;/strong&gt;，就可以得到显示屏一行有多少个像素点。这个值最终就可以保存在前面所打开的fb设备的成员变量&lt;strong&gt;stride&lt;/strong&gt;中。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当显示屏每一个像素所占用的位数等于&lt;strong&gt;32&lt;/strong&gt;的时候，那么前面所打开的fb设备的像素格式&lt;strong&gt;format&lt;/strong&gt;就会被设置为HAL_PIXEL_FORMAT_RGBX_8888，否则的话，就会被设置为HAL_PIXEL_FORMAT_RGB_565。另一方面，如果在编译的时候定义了&lt;strong&gt;NO_32BPP&lt;/strong&gt;宏，即不要使用32位来描述一个像素，那么函数fb_device_open就会强制将前面所打开的fb设备的像素格式format设置为HAL_PIXEL_FORMAT_RGB_565。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）函数&lt;strong&gt;mapFrameBuffer&lt;/strong&gt;除了用来获得系统帧缓冲区的信息之外，还会将系统帧缓冲区映射到当前进程的地址空间来。&lt;strong&gt;在Android系统中，Gralloc模块中的fb设备是由SurfaceFlinger服务来负责打开和管理的，而SurfaceFlinger服是运行System进程中的，因此，系统帧缓冲区实际上是映射到System进程的地址空间中的&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数mapFrameBuffer实现在文件hardware/libhardware/modules/gralloc/framebuffer.cpp，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;mapFrameBuffer&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;private_module_t&lt;/span&gt;* module)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    pthread_mutex_lock(&amp;amp;module-&amp;gt;lock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; err = mapFrameBufferLocked(module);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    pthread_mutex_unlock(&amp;amp;module-&amp;gt;lock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个函数调用了同一个文件中的另外一个函数mapFrameBufferLocked来初始化参数module以及将系统帧缓冲区映射到当前进程的地址空间来。&lt;/p&gt;
&lt;h3 id=&quot;映射内存过程&quot;&gt;&lt;a href=&quot;#映射内存过程&quot; class=&quot;headerlink&quot; title=&quot;映射内存过程&quot;&gt;&lt;/a&gt;映射内存过程&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数mapFrameBufferLocked的实现比较长，我们分段来阅读：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Part.1：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;mapFrameBufferLocked&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;private_module_t&lt;/span&gt;* module)&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// already initialized...  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (module-&amp;gt;framebuffer) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; * &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; device_template[] = &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;string&quot;&gt;&quot;/dev/graphics/fb%u&quot;&lt;/span&gt;,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;string&quot;&gt;&quot;/dev/fb%u&quot;&lt;/span&gt;,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; &amp;#125;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; fd = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; name[&lt;span class=&quot;number&quot;&gt;64&lt;/span&gt;];  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; ((fd==&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;) &amp;amp;&amp;amp; device_template[i]) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;built_in&quot;&gt;snprintf&lt;/span&gt;(name, &lt;span class=&quot;number&quot;&gt;64&lt;/span&gt;, device_template[i], &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        fd = open(name, O_RDWR, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        i++;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (fd &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -errno;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...... &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这段代码在首先在系统中检查是否存在设备文件/dev/graphics/fb0或者/dev/fb0。如果存在的话，那么就调用函数open来打开它，并且将得到的文件描述符保存在变量fd中。这样，接下来函数mapFrameBufferLocked就可以通过文件描述符fd来与内核中的帧缓冲区驱动程序交互。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Part.2：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;mapFrameBufferLocked&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;private_module_t&lt;/span&gt;* module)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.1&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; fb_fix_screeninfo finfo;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ioctl(fd, FBIOGET_FSCREENINFO, &amp;amp;finfo) == &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -errno;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; fb_var_screeninfo info;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ioctl(fd, FBIOGET_VSCREENINFO, &amp;amp;info) == &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -errno;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这几行代码分别通过IO控制命令FBIOGET_FSCREENINFO和FBIOGET_VSCREENINFO来获得系统帧缓冲区的信息，分别保存在fb_fix_screeninfo结构体finfo和fb_var_screeninfo结构体info中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Part.3：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;mapFrameBufferLocked&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;private_module_t&lt;/span&gt;* module)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.1&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.2&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    info.reserved[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;] = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    info.reserved[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;] = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    info.reserved[&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;] = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    info.xoffset = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    info.yoffset = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    info.activate = FB_ACTIVATE_NOW;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * Request NUM_BUFFERS screens (at lest 2 for page flipping)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    info.yres_virtual = info.yres * NUM_BUFFERS;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; flags = PAGE_FLIP;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;if&lt;/span&gt; USE_PAN_DISPLAY  &lt;span class=&quot;comment&quot;&gt;// 0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ioctl(fd, FBIOPAN_DISPLAY, &amp;amp;info) == &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGW(&lt;span class=&quot;string&quot;&gt;&quot;FBIOPAN_DISPLAY failed, page flipping not supported&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;else&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ioctl(fd, FBIOPUT_VSCREENINFO, &amp;amp;info) == &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGW(&lt;span class=&quot;string&quot;&gt;&quot;FBIOPUT_VSCREENINFO failed, page flipping not supported&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#&lt;span class=&quot;meta-keyword&quot;&gt;endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        info.yres_virtual = info.yres;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        flags &amp;amp;= ~PAGE_FLIP;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (info.yres_virtual &amp;lt; info.yres * &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// we need at least 2 for page-flipping&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        info.yres_virtual = info.yres;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        flags &amp;amp;= ~PAGE_FLIP;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGW(&lt;span class=&quot;string&quot;&gt;&quot;page flipping not supported (yres_virtual=%d, requested=%d)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                info.yres_virtual, info.yres*&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这段代码主要是用来设置设备显示屏的虚拟分辨率。结构体&lt;strong&gt;fb_var_screeninfo&lt;/strong&gt;的成员变量&lt;strong&gt;xres&lt;/strong&gt;和&lt;strong&gt;yres&lt;/strong&gt;用来描述显示屏的可视分辨率，而成员变量&lt;strong&gt;xres_virtual&lt;/strong&gt;和&lt;strong&gt;yres_virtual&lt;/strong&gt;用来描述显示屏的虚拟分辨率。这里保持可视分辨率以及虚拟分辨率的宽度值不变，而将虚拟分辨率的高度值设置为可视分辨率的高度值的&lt;strong&gt;NUM_BUFFERS&lt;/strong&gt;倍。NUM_BUFFERS是一个宏，它的值被定义为&lt;code&gt;2&lt;/code&gt;。这样，我们就可以将系统帧缓冲区划分为两个图形缓冲区来使用，即可以通过硬件来实现双缓冲技术。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在结构体fb_var_screeninfo中，与显示屏的可视分辨率和虚拟分辨率相关的另外两个成员变量是&lt;strong&gt;xoffset&lt;/strong&gt;和&lt;strong&gt;yoffset&lt;/strong&gt;，它们用来告诉帧缓冲区当前要渲染的图形缓冲区是哪一个。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这段代码最终是通过IO控制命令&lt;strong&gt;FBIOPUT_VSCREENINFO&lt;/strong&gt;来设置设备显示屏的虚拟分辨率以及像素格式的。如果设置失败，即调用函数&lt;strong&gt;ioctl&lt;/strong&gt;的返回值等于-1，那么很可能是因为系统帧缓冲区在硬件上不支持双缓冲，因此，接下来的代码就会重新将显示屏的虚拟分辨率的高度值设置为可视分辨率的高度值，并且将变量&lt;strong&gt;flags&lt;/strong&gt;的&lt;strong&gt;PAGE_FLIP&lt;/strong&gt;位置为0。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;另一方面，如果调用函数ioctl成功，但是最终获得的显示屏的虚拟分辨率的高度值小于可视分辨率的高度值的2倍，那么也说明系统帧缓冲区在硬件上不支持双缓冲。在这种情况下，接下来的代码也会重新将显示屏的虚拟分辨率的高度值设置为可视分辨率的高度值，并且将变量flags的PAGE_FLIP位置为0。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Part.4：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;mapFrameBufferLocked&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;private_module_t&lt;/span&gt;* module)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.1&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.2&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.3&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ioctl(fd, FBIOGET_VSCREENINFO, &amp;amp;info) == &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;)  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -errno;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;uint64_t&lt;/span&gt;  refreshQuotient =  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;(  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;uint64_t&lt;/span&gt;( info.upper_margin + info.lower_margin + info.yres )  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        * ( info.left_margin  + info.right_margin + info.xres )  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        * info.pixclock  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/* Beware, info.pixclock might be 0 under emulation, so avoid a &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; * division-by-0 here (SIGFPE on ARM) */&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; refreshRate = refreshQuotient &amp;gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ? (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;)(&lt;span class=&quot;number&quot;&gt;1000000000000000L&lt;/span&gt;LU / refreshQuotient) : &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (refreshRate == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// bleagh, bad info from the driver  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    refreshRate = &lt;span class=&quot;number&quot;&gt;60&lt;/span&gt;*&lt;span class=&quot;number&quot;&gt;1000&lt;/span&gt;;  &lt;span class=&quot;comment&quot;&gt;// 60 Hz  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这段代码再次通过IO控制命令&lt;strong&gt;FBIOGET_VSCREENINFO&lt;/strong&gt;来获得系统帧缓冲区的可变属性信息，并且保存在&lt;strong&gt;fb_var_screeninfo&lt;/strong&gt;结构体&lt;strong&gt;info&lt;/strong&gt;中，接下来再计算设备显示屏的刷新频率。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;显示屏的刷新频率与显示屏的扫描时序相关。显示屏的扫描时序可以参考Kernel代码目录下的Documentation/fb/framebuffer.txt文件。我们结合这个txt文件中的一幅图来简单说明上述代码是如何计算显示屏的刷新频率的：&lt;br&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%B8%80%29----Android%E5%9B%BE%E5%BD%A2%E6%98%BE%E7%A4%BA%E4%B9%8BHAL%E5%B1%82Gralloc%E6%A8%A1%E5%9D%97%E5%AE%9E%E7%8E%B0/framebuffer.jpg&quot; alt=&quot;显示屏扫描时序示意图&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;中间由xres和yres组成的区域即为显示屏的图形绘制区，在绘制区的上、下、左和右分别有四个边距upper_margin、lower_margin、left_margin和right_margin。此外，在显示屏的最右边以及最下边还有一个水平同步区域hsync_len和一个垂直同步区域vsync_len。电子枪按照从左到右、从上到下的顺序来显示屏中打点，从而可以将要渲染的图形显示在屏幕中。前面所提到的区域信息分别保存在fb_var_screnninfo结构体info的成员变量xres、yres、upper_margin、lower_margin、left_margin、right_margin、hsync_len和vsync_len。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;电子枪每在xres和yres所组成的区域中打一个点所花费的时间记录在fb_var_screnninfo结构体info的成员变量pixclock，单位为pico seconds，即10E-12秒。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;电子枪从左到右扫描完成一行之后，都会处理关闭状态，并且会重新折回到左边去。由于电子枪在从右到左折回的过程中不需要打点，因此，这个过程会比从左到右扫描屏幕的过程要快，这个折回的时间大概就等于在xres和yres所组成的区域扫描（left_margin+right_margin）个点的时间。这样，我们就可以认为每渲染一行需要的时间为（xres + left_margin + right_margin）* pixclock。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;同样，电子枪从上到下扫描完成显示屏之后，需要从右下角折回到左上角去，折回的时间大概等于在xres和yres所组成的区域中扫描（upper_margin + lower_margin）行所需要的时间。这样，我们就可以认为每渲染一屏图形所需要的时间等于在xres和yres所组成的区域中扫描（yres + upper_margin + lower_margin）行所需要的时间。由于在xres和yres所组成的区域中扫描一行所需要的时间为（xres + left_margin + right_margin）&lt;em&gt; pixclock，因此，每渲染一屏图形所需要的总时间就等于（yres + upper_margin + lower_margin）&lt;/em&gt; （xres + left_margin + right_margin）* pixclock。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;每渲染一屏图形需要的总时间经过计算之后，就保存在变量refreshQuotient中。注意，变量refreshQuotient所描述的时间的单位为1E-12秒。这样，将变量refreshQuotient的值倒过来，就可以得到设备显示屏的刷新频率。将这个频率值乘以10E15次方之后，就得到一个单位为10E-3 HZ的刷新频率，保存在变量refreshRate中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当Android系统在模拟器运行的时候，保存在fb_var_screnninfo结构体info的成员变量pixclock中的值可能等于0。在这种情况下，前面计算得到的变量refreshRate的值就会等于0。在这种情况下，接下来的代码会将变量refreshRate的值设置为60 &lt;em&gt; 1000 &lt;/em&gt; 10E-3 HZ，即将显示屏的刷新频率设置为60HZ。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Part.5：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;mapFrameBufferLocked&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;private_module_t&lt;/span&gt;* module)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.1&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.2&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.3&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.4&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;(info.width) &amp;lt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; || &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;(info.height) &amp;lt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// the driver doesn&#39;t return that information  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// default to 160 dpi  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    info.width  = ((info.xres * &lt;span class=&quot;number&quot;&gt;25.4f&lt;/span&gt;)/&lt;span class=&quot;number&quot;&gt;160.0f&lt;/span&gt; + &lt;span class=&quot;number&quot;&gt;0.5f&lt;/span&gt;);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    info.height = ((info.yres * &lt;span class=&quot;number&quot;&gt;25.4f&lt;/span&gt;)/&lt;span class=&quot;number&quot;&gt;160.0f&lt;/span&gt; + &lt;span class=&quot;number&quot;&gt;0.5f&lt;/span&gt;);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;float&lt;/span&gt; xdpi = (info.xres * &lt;span class=&quot;number&quot;&gt;25.4f&lt;/span&gt;) / info.width;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;float&lt;/span&gt; ydpi = (info.yres * &lt;span class=&quot;number&quot;&gt;25.4f&lt;/span&gt;) / info.height;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;float&lt;/span&gt; fps  = refreshRate / &lt;span class=&quot;number&quot;&gt;1000.0f&lt;/span&gt;; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这段代码首先计算显示屏的密度，即每英寸有多少个像素点，分别宽度和高度两个维度，分别保存在变量xdpi和ydpi中。注意，fb_var_screeninfo结构体info的成员变量width和height用来描述显示屏的宽度和高度，它们是以&lt;strong&gt;毫米&lt;/strong&gt;（mm）为单位的。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这段代码接着再将前面计算得到的显示屏刷新频率的单位由10E-3 HZ转换为HZ，即帧每秒，并且保存在变量fps中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Part.6：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;mapFrameBufferLocked&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;private_module_t&lt;/span&gt;* module)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.1&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.2&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.3&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.4&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.5&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ioctl(fd, FBIOGET_FSCREENINFO, &amp;amp;finfo) == &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;)  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -errno;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (finfo.smem_len &amp;lt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -errno;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;module-&amp;gt;flags = flags;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;module-&amp;gt;info = info;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;module-&amp;gt;finfo = finfo;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;module-&amp;gt;xdpi = xdpi;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;module-&amp;gt;ydpi = ydpi;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;module-&amp;gt;fps = fps;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这段代码再次通过IO控制命令&lt;strong&gt;FBIOGET_FSCREENINFO&lt;/strong&gt;来获得系统帧缓冲区的固定信息，并且保存在&lt;strong&gt;fb_fix_screeninfo&lt;/strong&gt;结构体&lt;strong&gt;finfo&lt;/strong&gt;中，接下来再使用fb_fix_screeninfo结构体finfo以及前面得到的系统帧缓冲区的其它信息来初始化参数&lt;strong&gt;module&lt;/strong&gt;所描述的一个&lt;strong&gt;private_module_t&lt;/strong&gt;结构体。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Part.7：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;mapFrameBufferLocked&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;private_module_t&lt;/span&gt;* module)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.1&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.2&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.3&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.4&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.5&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.6&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/* &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * map the framebuffer &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; err;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    module-&amp;gt;framebuffer = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;(dup(fd), fbSize, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    module-&amp;gt;numBuffers = info.yres_virtual / info.yres;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    module-&amp;gt;bufferMask = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;* vaddr = mmap(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (vaddr == MAP_FAILED) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        LOGE(&lt;span class=&quot;string&quot;&gt;&quot;Error mapping the framebuffer (%s)&quot;&lt;/span&gt;, strerror(errno));  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -errno;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    module-&amp;gt;framebuffer-&amp;gt;base = &lt;span class=&quot;keyword&quot;&gt;intptr_t&lt;/span&gt;(vaddr);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;built_in&quot;&gt;memset&lt;/span&gt;(vaddr, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, fbSize);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;表达式&lt;strong&gt;finfo.line_length * info.yres_virtual&lt;/strong&gt;计算的是整个系统帧缓冲区的大小，它的值等于显示屏行数（虚拟分辨率的高度值，&lt;strong&gt;info.yres_virtual&lt;/strong&gt;）乘以每一行所占用的字节数（&lt;strong&gt;finfo.line_length&lt;/strong&gt;）。函数&lt;strong&gt;roundUpToPageSize&lt;/strong&gt;用来将整个系统帧缓冲区的大小对齐到页面边界。对齐后的大小保存在变量&lt;strong&gt;fbSize&lt;/strong&gt;中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;表达式&lt;strong&gt;finfo.yres_virtual / info.yres&lt;/strong&gt;计算的是整个系统帧缓冲区可以划分为多少个图形缓冲区来使用，这个数值保存在参数module所描述的一个private_module_t结构体的成员变量&lt;strong&gt;nmBuffers&lt;/strong&gt;中。参数module所描述的一个private_module_t结构体的另外一个成员变量&lt;strong&gt;bufferMask&lt;/strong&gt;的值接着被设置为0，表示系统帧缓冲区中的所有图形缓冲区都是处于空闲状态，即它们可以分配出去给应用程序使用。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;系统帧缓冲区是通过调用函数&lt;strong&gt;mmap&lt;/strong&gt;来映射到当前进程的地址空间来的。映射后得到的地址空间使用一个&lt;strong&gt;private_handle_t&lt;/strong&gt;结构体来描述，这个结构体的成员变量&lt;strong&gt;base&lt;/strong&gt;保存的即为系统帧缓冲区在当前进程的地址空间中的起始地址。这样，Gralloc模块以后就可以从这块地址空间中分配图形缓冲区给当前进程使用。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;至此，fb设备的打开过程就分析完成了。在打开fb设备的过程中，Gralloc模块还完成了对系统帧缓冲区的初始化工作。接下来我们继续分析Gralloc模块是如何分配图形缓冲区给用户空间的应用程序使用的。&lt;/p&gt;
&lt;h2 id=&quot;分配图形缓冲区&quot;&gt;&lt;a href=&quot;#分配图形缓冲区&quot; class=&quot;headerlink&quot; title=&quot;分配图形缓冲区&quot;&gt;&lt;/a&gt;分配图形缓冲区&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;前面提到，用户空间的应用程序用到的图形缓冲区是由Gralloc模块中的函数gralloc_alloc来分配的，这个函数实现在文件hardware/libhardware/modules/gralloc/gralloc.cpp中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;gralloc_alloc&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;alloc_device_t&lt;/span&gt;* dev,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; h, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; format, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; usage,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt;* pHandle, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;* pStride)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!pHandle || !pStride)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -EINVAL;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; size, stride;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; align = &lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; bpp = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt; (format) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HAL_PIXEL_FORMAT_RGBA_8888:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HAL_PIXEL_FORMAT_RGBX_8888:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HAL_PIXEL_FORMAT_BGRA_8888:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            bpp = &lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HAL_PIXEL_FORMAT_RGB_888:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            bpp = &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HAL_PIXEL_FORMAT_RGB_565:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; HAL_PIXEL_FORMAT_RAW_SENSOR:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            bpp = &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;default&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -EINVAL;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; bpr = (w*bpp + (align&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;)) &amp;amp; ~(align&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    size = bpr * h;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    stride = bpr / bpp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (usage &amp;amp; GRALLOC_USAGE_HW_FB) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        err = gralloc_alloc_framebuffer(dev, size, usage, pHandle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        err = gralloc_alloc_buffer(dev, size, usage, pHandle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    *pStride = stride;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;参数format用来描述要分配的图形缓冲区的颜色格式。当format值等于HAL_PIXEL_FORMAT_RGBA_8888、HAL_PIXEL_FORMAT_RGBX_8888或者HAL_PIXEL_FORMAT_BGRA_8888的时候，一个像素需要使用32位来表示，即4个字节。当format值等于HAL_PIXEL_FORMAT_RGB_888的时候，一个像素需要使用24位来描述，即3个字节。当format值等于HAL_PIXEL_FORMAT_RGB_565、HAL_PIXEL_FORMAT_RGBA_5551或者HAL_PIXEL_FORMAT_RGBA_4444的时候，一个像需要使用16位来描述，即2个字节。最终一个像素需要使用的字节数保存在变量bpp中。&lt;/li&gt;
&lt;li&gt;参数w表示要分配的图形缓冲区所保存的图像的宽度，将它乘以bpp，就可以得到保存一行像素所需要使用的字节数。我们需要将这个字节数对齐到4个字节边界，最后得到一行像素所需要的字节数就保存在变量bpr中。&lt;/li&gt;
&lt;li&gt;参数h表示要分配的图形缓冲区所保存的图像的高度，将它乘以bpr，就可以得到保存整个图像所需要使用的字节数。&lt;/li&gt;
&lt;li&gt;将变量bpr的值除以变量bpp的值，就得到要分配的图形缓冲区一行包含有多少个像素点，这个结果需要保存在输出参数pStride中，以便可以返回给调用者。&lt;/li&gt;
&lt;li&gt;参数usage用来描述要分配的图形缓冲区的用途。如果是用来在系统帧缓冲区中渲染的，即参数usage的GRALLOC_USAGE_HW_FB位等于1，那么就必须要系统帧缓冲区中分配，否则的话，就在内存中分配。注意，在内存中分配的图形缓冲区，最终是需要拷贝到系统帧缓冲区去的，以便可以将它所描述的图形渲染出来。&lt;/li&gt;
&lt;li&gt;函数gralloc_alloc_framebuffer用来在系统帧缓冲区中分配图形缓冲区，而函数gralloc_alloc_buffer用来在内存在分配图形缓冲区，接下来我们就分别分析这两个函数的实现。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;系统帧缓冲区中分配图形缓冲区&quot;&gt;&lt;a href=&quot;#系统帧缓冲区中分配图形缓冲区&quot; class=&quot;headerlink&quot; title=&quot;系统帧缓冲区中分配图形缓冲区&quot;&gt;&lt;/a&gt;系统帧缓冲区中分配图形缓冲区&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数gralloc_alloc_framebuffer实现在文件hardware/libhardware/modules/gralloc/gralloc.cpp中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;gralloc_alloc_framebuffer&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;alloc_device_t&lt;/span&gt;* dev,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; size, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; usage, &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt;* pHandle)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;private_module_t&lt;/span&gt;* m = &lt;span class=&quot;keyword&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;private_module_t&lt;/span&gt;*&amp;gt;(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            dev-&amp;gt;common.module);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    pthread_mutex_lock(&amp;amp;m-&amp;gt;lock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    pthread_mutex_unlock(&amp;amp;m-&amp;gt;lock);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个函数调用了另外一个函数gralloc_alloc_framebuffer_locked来分配图形缓冲区。函数gralloc_alloc_framebuffer_locked也是实现在文件hardware/libhardware/modules/gralloc/gralloc.cpp中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;gralloc_alloc_framebuffer_locked&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;alloc_device_t&lt;/span&gt;* dev,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; size, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; usage, &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt;* pHandle)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;private_module_t&lt;/span&gt;* m = &lt;span class=&quot;keyword&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;private_module_t&lt;/span&gt;*&amp;gt;(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            dev-&amp;gt;common.module);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// allocate the framebuffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (m-&amp;gt;framebuffer == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// initialize the framebuffer, the framebuffer is mapped once&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// and forever.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; err = mapFrameBufferLocked(m);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; bufferMask = m-&amp;gt;bufferMask;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; numBuffers = m-&amp;gt;numBuffers;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; bufferSize = m-&amp;gt;finfo.line_length * m-&amp;gt;info.yres;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (numBuffers == &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// If we have only one buffer, we never use page-flipping. Instead,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// we return a regular buffer which will be memcpy&#39;ed to the main&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// screen when post is called.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; newUsage = (usage &amp;amp; ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; gralloc_alloc_buffer(dev, bufferSize, newUsage, pHandle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (bufferMask &amp;gt;= ((&lt;span class=&quot;number&quot;&gt;1L&lt;/span&gt;U&amp;lt;&amp;lt;numBuffers)&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// We ran out of buffers.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -ENOMEM;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// create a &quot;fake&quot; handles for it&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;intptr_t&lt;/span&gt; vaddr = &lt;span class=&quot;keyword&quot;&gt;intptr_t&lt;/span&gt;(m-&amp;gt;framebuffer-&amp;gt;base);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;* hnd = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;(dup(m-&amp;gt;framebuffer-&amp;gt;fd), size,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;::PRIV_FLAGS_FRAMEBUFFER);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// find a free slot&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ; i&amp;lt;numBuffers ; i++) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((bufferMask &amp;amp; (&lt;span class=&quot;number&quot;&gt;1L&lt;/span&gt;U&amp;lt;&amp;lt;i)) == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            m-&amp;gt;bufferMask |= (&lt;span class=&quot;number&quot;&gt;1L&lt;/span&gt;U&amp;lt;&amp;lt;i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        vaddr += bufferSize;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    hnd-&amp;gt;base = vaddr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    hnd-&amp;gt;offset = vaddr - &lt;span class=&quot;keyword&quot;&gt;intptr_t&lt;/span&gt;(m-&amp;gt;framebuffer-&amp;gt;base);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    *pHandle = hnd;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在系统帧缓冲区分配图形缓冲区之前，首先要对系统帧缓冲区进行过初始化，即这里的变量&lt;strong&gt;m&lt;/strong&gt;所指向的一个&lt;strong&gt;private_module_t&lt;/strong&gt;结构体的成员变量&lt;strong&gt;framebuffer&lt;/strong&gt;的值不能等于NULL。如果等于NULL的话，那么就必须要调用另外一个函数&lt;strong&gt;mapFrameBufferLocked&lt;/strong&gt;来初始化系统帧缓冲区。初始化系统帧缓冲区的过程可以参考前面的内容。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;变量&lt;strong&gt;bufferMask&lt;/strong&gt;用来描述系统帧缓冲区的使用情况，而变量&lt;strong&gt;numBuffers&lt;/strong&gt;用来描述系统帧缓冲区可以划分为多少个图形缓冲区来使用，另外一个变量&lt;strong&gt;bufferSize&lt;/strong&gt;用来描述设备显示屏一屏内容所占用的内存的大小。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果系统帧缓冲区只有一个图形缓冲区大小，即变量numBuffers的值等于1，那么这个图形缓冲区就始终用作系统主图形缓冲区来使用。在这种情况下，我们就不能够在系统帧缓冲区中分配图形缓冲区来给用户空间的应用程序使用，因此，&lt;strong&gt;这时候就会转向内存中来分配图形缓冲区&lt;/strong&gt;，即调用函数&lt;strong&gt;gralloc_alloc_buffer&lt;/strong&gt;来分配图形缓冲区。注意，&lt;strong&gt;这时候分配的图形缓冲区的大小为一屏内容的大小，即bufferSize&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果bufferMask的值大于等于((1LU&amp;lt;&amp;lt;numBuffers)-1)的值，那么就说明系统帧缓冲区中的图形缓冲区全部都分配出去了，这时候分配图形缓冲区就失败了。例如，假设图形缓冲区的个数为2，那么((1LU&amp;lt;&amp;lt;numBuffers)-1)的值就等于3，即二制制0x11。如果这时候bufferMask的值也等于0x11，那么就表示第一个和第二个图形缓冲区都已经分配出去了。因此，这时候就不能再在系统帧缓冲区中分配图形缓冲区。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;假设此时系统帧缓冲区中尚有空闲的图形缓冲区的，接下来函数就会创建一个private_handle_t结构体&lt;strong&gt;hnd&lt;/strong&gt;来描述这个即将要分配出去的图形缓冲区。注意，这个图形缓冲区的标志值等于&lt;strong&gt;PRIV_FLAGS_FRAMEBUFFER&lt;/strong&gt;，即表示这是一块在系统帧缓冲区中分配的图形缓冲区。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;接下来的for循环从低位到高位检查变量bufferMask的值，并且找到第一个值等于0的位，这样就可以知道在系统帧缓冲区中，第几个图形缓冲区的是空闲的。注意，变量&lt;strong&gt;vadrr&lt;/strong&gt;的值开始的时候指向系统帧缓冲区的基地址，在下面的for循环中，每循环一次它的值都会增加bufferSize。从这里就可以看出，每次从系统帧缓冲区中分配出去的图形缓冲区的大小都是刚好等于显示屏一屏内容大小的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;最后分配出去的图形缓冲区的开始地址就保存在前面所创建的private_handle_t结构体&lt;strong&gt;hnd&lt;/strong&gt;的成员变量&lt;strong&gt;base&lt;/strong&gt;中，这样，用户空间的应用程序就可以直接将要渲染的图形内容拷贝到这个地址上去，这就相当于是直接将图形渲染到系统帧缓冲区中去。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在将private_handle_t结构体hnd返回给调用者之前，还需要设置它的成员变量&lt;strong&gt;offset&lt;/strong&gt;，以便可以知道它所描述的图形缓冲区的起始地址相对于系统帧缓冲区的基地址的偏移量。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;至此，在系统帧缓冲区中分配图形缓冲区的过程就分析完成了，接下来我们再分析在内存在分析图形缓冲区的过程，即分析函数&lt;strong&gt;gralloc_alloc_buffer&lt;/strong&gt;的实现。&lt;/p&gt;
&lt;h3 id=&quot;内存中分配图形缓冲区&quot;&gt;&lt;a href=&quot;#内存中分配图形缓冲区&quot; class=&quot;headerlink&quot; title=&quot;内存中分配图形缓冲区&quot;&gt;&lt;/a&gt;内存中分配图形缓冲区&lt;/h3&gt;&lt;p&gt; &amp;#160; &amp;#160; &amp;#160; &amp;#160;函数gralloc_alloc_buffer也是实现在文件hardware/libhardware/modules/gralloc/gralloc.cpp中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;gralloc_alloc_buffer&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;alloc_device_t&lt;/span&gt;* dev,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; size, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; usage, &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt;* pHandle)&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; err = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; fd = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    size = roundUpToPageSize(size);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    fd = ashmem_create_region(&lt;span class=&quot;string&quot;&gt;&quot;gralloc-buffer&quot;&lt;/span&gt;, size);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (fd &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        LOGE(&lt;span class=&quot;string&quot;&gt;&quot;couldn&#39;t create ashmem (%s)&quot;&lt;/span&gt;, strerror(-errno));  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        err = -errno;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;* hnd = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;(fd, size, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt;* module = &lt;span class=&quot;keyword&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt;*&amp;gt;(  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                dev-&amp;gt;common.module);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        err = mapBuffer(module, hnd);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            *pHandle = hnd;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    LOGE_IF(err, &lt;span class=&quot;string&quot;&gt;&quot;gralloc failed err=%s&quot;&lt;/span&gt;, strerror(-err));  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt; &amp;#160; &amp;#160; &amp;#160; &amp;#160;这个函数的实现很简单，它首先调用函数&lt;strong&gt;ashmem_create_region&lt;/strong&gt;来创建一块匿名共享内存，接着再在这块匿名共享内存上分配一个图形缓冲区。注意，这个图形缓冲区也是使用一个private_handle_t结构体来描述的，不过这个图形缓冲区的标志值等于0，以区别于在系统帧缓冲区中分配的图形缓冲区。匿名共享内存的知识还没有入坑，以后再看。。。。。。&lt;/p&gt;
&lt;p&gt; &amp;#160; &amp;#160; &amp;#160; &amp;#160;从匿名共享内存中分配的图形缓冲区还需要映射到进程的地址空间来，然后才可以使用，这是通过调用函数mapBuffer来实现的。&lt;/p&gt;
&lt;p&gt; &amp;#160; &amp;#160; &amp;#160; &amp;#160;函数mapBuffer实现在文件hardware/libhardware/modules/gralloc/mapper.cpp中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;mapBuffer&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* module,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;* hnd)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;* vaddr;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; gralloc_map(module, hnd, &amp;amp;vaddr);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt; &amp;#160; &amp;#160; &amp;#160; &amp;#160;它通过调用另外一个函数&lt;strong&gt;gralloc_map&lt;/strong&gt;来将参数hnd所描述的一个图形缓冲区映射到当前进程的地址空间来。后面在分析图形缓冲区的注册过程时，我们再分析函数gralloc_map的实现。&lt;/p&gt;
&lt;p&gt; &amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;注意，在Android系统中，在系统帧缓冲区中分配的图形缓冲区是在SurfaceFlinger服务中使用的，而在内存中分配的图形缓冲区既可以在SurfaceFlinger服务中使用，也可以在其它的应用程序中使用。当其它的应用程序需要使用图形缓冲区的时候，它们就会请求SurfaceFlinger服务为它们分配，因此，对于其它的应用程序来说，它们只需要将SurfaceFlinger服务返回来的图形缓冲区映射到自己的进程地址空间来使用就可以了，这就是后面我们所要分析的图形缓冲区的注册过程&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;至此，图形缓冲区的分配过程就分析完成了，接下来我们继续分析图形缓冲区的释放过程。&lt;/p&gt;
&lt;h2 id=&quot;图形缓冲区的释放过程&quot;&gt;&lt;a href=&quot;#图形缓冲区的释放过程&quot; class=&quot;headerlink&quot; title=&quot;图形缓冲区的释放过程&quot;&gt;&lt;/a&gt;图形缓冲区的释放过程&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;前面提到，用户空间的应用程序用到的图形缓冲区是由Gralloc模块中的函数gralloc_free来释放的，这个函数实现在文件hardware/libhardware/modules/gralloc/gralloc.cpp中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;gralloc_free&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;alloc_device_t&lt;/span&gt;* dev,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt; handle)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;::validate(handle) &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -EINVAL;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* hnd = &lt;span class=&quot;keyword&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;*&amp;gt;(handle);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hnd-&amp;gt;flags &amp;amp; &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;::PRIV_FLAGS_FRAMEBUFFER) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// free this buffer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;private_module_t&lt;/span&gt;* m = &lt;span class=&quot;keyword&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;private_module_t&lt;/span&gt;*&amp;gt;(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                dev-&amp;gt;common.module);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; bufferSize = m-&amp;gt;finfo.line_length * m-&amp;gt;info.yres;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; index = (hnd-&amp;gt;base - m-&amp;gt;framebuffer-&amp;gt;base) / bufferSize;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        m-&amp;gt;bufferMask &amp;amp;= ~(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&amp;lt;&amp;lt;index); &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123; &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt;* module = &lt;span class=&quot;keyword&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt;*&amp;gt;(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                dev-&amp;gt;common.module);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        terminateBuffer(module, &lt;span class=&quot;keyword&quot;&gt;const_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;*&amp;gt;(hnd));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    close(hnd-&amp;gt;fd);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;delete&lt;/span&gt; hnd;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;要释放的图形缓冲区使用参数&lt;strong&gt;handle&lt;/strong&gt;来描述。前面提到，从Gralloc模块中分配的图形缓冲区是使用private_handle_t结构体来描述的，因此，这里的参数handle应该指向一个&lt;strong&gt;private_handle_t&lt;/strong&gt;结构体，这是通过调用private_handle_t类的静态成员函数&lt;strong&gt;validate&lt;/strong&gt;来验证的。private_handle_t类的静态成员函数validate的实现可以参考前面的内容。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;要释放的图形缓冲区有可能是在系统帧缓冲区分配的，也有可能是在内存中分配的，这可以通过检查它的标志值flags的&lt;strong&gt;PRIV_FLAGS_FRAMEBUFFER&lt;/strong&gt;位是否等于1来确认。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果要释放的图形缓冲区是在系统帧缓冲区中分配的，那么首先要知道这个图形缓冲区是系统帧缓冲区的第&lt;strong&gt;index&lt;/strong&gt;个位置，接着再将变量m所描述的一个private_module_t结构体的成员变量&lt;strong&gt;bufferMask&lt;/strong&gt;的第index位重置为0即可。我们只需要将要释放的图形缓冲区的开始地址减去系统帧缓冲区的基地址，再除以一个图形缓冲区的大小，就可以知道要释放的图形缓冲区是系统帧缓冲区的第几个位置。这个过程刚好是在系统帧缓冲区中分配图形缓冲区的逆操作。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果要释放的图形缓冲区是内存中分配的，那么只需要调用另外一个函数&lt;strong&gt;terminateBuffer&lt;/strong&gt;来解除要释放的图形缓冲区在当前进程的地址空间中的映射。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;最后，这个函数还会将用来描述要释放的图形缓冲区的private_handle_t结构体所占用的内存释放掉，并且将要要释放的图形缓冲区所在的系统帧缓冲区或者匿名共享内存的文件描述符关闭掉。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数terminateBuffer实现在文件hardware/libhardware/modules/gralloc/mapper.cpp中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;terminateBuffer&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* module,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;* hnd)&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hnd-&amp;gt;base) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// this buffer was mapped, unmap it now  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        gralloc_unmap(module, hnd);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;它通过调用另外一个函数&lt;strong&gt;gralloc_unmap&lt;/strong&gt;来解除参数hnd所描述的一个图形缓冲区在当前进程的地址空间中的映射。后面在分析图形缓冲区的注销过程时，我们再详细分析函数gralloc_unmap的实现。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;至此，图形缓冲区的释放过程就分析完成了，接下来我们继续分析图形缓冲区的注册过程。&lt;/p&gt;
&lt;h2 id=&quot;图形缓冲区的注册过程&quot;&gt;&lt;a href=&quot;#图形缓冲区的注册过程&quot; class=&quot;headerlink&quot; title=&quot;图形缓冲区的注册过程&quot;&gt;&lt;/a&gt;图形缓冲区的注册过程&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;前面提到，在Android系统中，所有的图形缓冲区都是由SurfaceFlinger服务分配的，而当一个图形缓冲区被分配的时候，它会同时被映射到请求分配的进程的地址空间去，即分配的过程同时也包含了注册的过程。但是对用户空间的其它的应用程序来说，它们所需要的图形缓冲区是在由SurfaceFlinger服务分配的，因此，当它们得到SurfaceFlinger服务分配的图形缓冲区之后，还需要将这块图形缓冲区映射到自己的地址空间来，以便可以使用这块图形缓冲区。这个映射的过程即为我们接下来要分析的图形缓冲区注册过程&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;前面还提到，注册图形缓冲区的操作是由Gralloc模块中的函数&lt;strong&gt;gralloc_register_buffer&lt;/strong&gt;来实现的，这个函数实现在文件hardware/libhardware/modules/gralloc/mapper.cpp中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;gralloc_register_buffer&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* module,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt; handle)&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;::validate(handle) &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -EINVAL;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// if this handle was created in this process, then we keep it as is.  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; err = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;* hnd = (&lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;*)handle;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hnd-&amp;gt;pid != getpid()) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; *vaddr;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        err = gralloc_map(module, handle, &amp;amp;vaddr);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个函数首先验证参数&lt;strong&gt;handle&lt;/strong&gt;指向的一块图形缓冲区的确是由Gralloc模块分配的，方法是调用private_handle_t类的静态成员函数validate来验证，即如果参数handle指向的是一个private_handle_t结构体，那么它所指向的一块图形缓冲区就是由Gralloc模块分配的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;通过了上面的检查之后，函数&lt;strong&gt;gralloc_register_buffer&lt;/strong&gt;还需要检查当前进程是否就是请求Gralloc模块分配图形缓冲区hnd的进程。如果是的话，那么当前进程在请求Gralloc模块分配图形缓冲区hnd的时候，就已经将图形缓冲区hnd映射进自己的地址空间来了，因此，这时候就不需要重复在当前进程中注册这个图形缓冲区。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;真正执行注册图形缓冲区的操作是由函数&lt;strong&gt;gralloc_map&lt;/strong&gt;来实现的，这个函数也是实现文件hardware/libhardware/modules/gralloc/mapper.cpp中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;gralloc_map&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* module,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt; handle,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;** vaddr)&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;* hnd = (&lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;*)handle;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!(hnd-&amp;gt;flags &amp;amp; &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;::PRIV_FLAGS_FRAMEBUFFER)) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; size = hnd-&amp;gt;size;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;* mappedAddress = mmap(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, size,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                PROT_READ|PROT_WRITE, MAP_SHARED, hnd-&amp;gt;fd, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mappedAddress == MAP_FAILED) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            LOGE(&lt;span class=&quot;string&quot;&gt;&quot;Could not mmap %s&quot;&lt;/span&gt;, strerror(errno));  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -errno;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        hnd-&amp;gt;base = &lt;span class=&quot;keyword&quot;&gt;intptr_t&lt;/span&gt;(mappedAddress) + hnd-&amp;gt;offset;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//LOGD(&quot;gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p&quot;,  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//        hnd-&amp;gt;fd, hnd-&amp;gt;offset, hnd-&amp;gt;size, mappedAddress);  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    *vaddr = (&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;*)hnd-&amp;gt;base;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;由于在系统帧缓冲区中分配的图形缓冲区只在SurfaceFlinger服务中使用，而SurfaceFlinger服务在初始化系统帧缓冲区的时候，已经将系统帧缓冲区映射到自己所在的进程中来了，因此，函数gralloc_map如果发现要注册的图形缓冲区是在系统帧缓冲区分配的时候，那么就不需要再执行映射图形缓冲区的操作了。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果要注册的图形缓冲区是在内存中分配的，即它的标志值flags的PRIV_FLAGS_FRAMEBUFFER位等于1，那么接下来就需要将它映射到当前进程的地址空间来了。&lt;strong&gt;由于要注册的图形缓冲区是在文件描述符hnd-&amp;gt;fd所描述的一块匿名共享内存中分配的，因此，我们只需要将文件描述符hnd-&amp;gt;fd所描述的一块匿名共享内存映射到当前进程的地址空间来，就可以将参数hnd所描述的一个图形缓冲区映射到当前进程的地址空间来&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;由于映射文件描述符hnd-&amp;gt;fd得到的是一整块匿名共享内存在当前进程地址空间的基地址，而要注册的图形缓冲区可能只占据这块匿名共享内存的某一小部分，因此，我们还需要将要注册的图形缓冲区的在被映射的匿名共享内存中的偏移量&lt;strong&gt;hnd-&amp;gt;offset&lt;/strong&gt;加上被映射的匿名共享内存的基地址&lt;strong&gt;hnd-&amp;gt;base&lt;/strong&gt;，才可以得到要注册的图形缓冲区在当前进程中的访问地址，这个地址最终又被写入到&lt;strong&gt;hnd-&amp;gt;base&lt;/strong&gt;中去。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;注册图形缓冲区的过程就是这么简单，接下来我们再分析图形缓冲区的注销过程。&lt;/p&gt;
&lt;h2 id=&quot;图形缓冲区的注销过程&quot;&gt;&lt;a href=&quot;#图形缓冲区的注销过程&quot; class=&quot;headerlink&quot; title=&quot;图形缓冲区的注销过程&quot;&gt;&lt;/a&gt;图形缓冲区的注销过程&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;图形缓冲区使用完成之后，就需要从当前进程中注销。前面提到，注销图形缓冲区是由Gralloc模块中的函数&lt;strong&gt;gralloc_unregister_buffer&lt;/strong&gt;来实现的，这个函数实现在文件hardware/libhardware/modules/gralloc/mapper.cpp中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;gralloc_unregister_buffer&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* module,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt; handle)&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;::validate(handle) &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -EINVAL;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// never unmap buffers that were created in this process  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;* hnd = (&lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;*)handle;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hnd-&amp;gt;pid != getpid()) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hnd-&amp;gt;base) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            gralloc_unmap(module, handle);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个函数同样是首先调用private_handle_t类的静态成员函数validate来验证参数handle指向的一块图形缓冲区的确是由Gralloc模块分配的，接着再将将参数handle指向的一块图形缓冲区转换为一个private_handle_t结构体hnd来访问。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;一块图形缓冲区只有被注册过，即被Gralloc模块中的函数gralloc_register_buffer注册过，才需要注销，而由函数gralloc_register_buffer注册的图形缓冲区都不是由当前进程分配的，因此，当前进程在注销一个图形缓冲区的时候，会检查要注销的图形缓冲区是否是由自己分配的。如果是由自己分配的话，那么它什么也不做就返回了。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;假设要注销的图形缓冲区hnd不是由当前进程分配的，那么接下来就会调用另外一个函数&lt;strong&gt;galloc_unmap&lt;/strong&gt;来注销图形缓冲区hnd。函数galloc_unmap也是实现在文件hardware/libhardware/modules/gralloc/mapper.cpp中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;gralloc_unmap&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* module,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt; handle)&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;* hnd = (&lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;*)handle;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!(hnd-&amp;gt;flags &amp;amp; &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;::PRIV_FLAGS_FRAMEBUFFER)) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;* base = (&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;*)hnd-&amp;gt;base;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; size = hnd-&amp;gt;size;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//LOGD(&quot;unmapping from %p, size=%d&quot;, base, size);  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (munmap(base, size) &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            LOGE(&lt;span class=&quot;string&quot;&gt;&quot;Could not unmap %s&quot;&lt;/span&gt;, strerror(errno));  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    hnd-&amp;gt;base = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个函数的实现与前面所分析的函数gralloc_map的实现是类似的，只不过它执行的是相反的操作，即将解除一个指定的图形缓冲区在当前进程的地址空间中的映射，从而完成对这个图形缓冲区的注销工作。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这样，图形缓冲区的注销过程就分析完成了，接下来我们再继续分析一个图形缓冲区是如何被渲染到系统帧缓冲区去的，即它的内容是如何绘制在设备显示屏中的。&lt;/p&gt;
&lt;h2 id=&quot;图形缓冲区的渲染过程&quot;&gt;&lt;a href=&quot;#图形缓冲区的渲染过程&quot; class=&quot;headerlink&quot; title=&quot;图形缓冲区的渲染过程&quot;&gt;&lt;/a&gt;图形缓冲区的渲染过程&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;用户空间的应用程序将画面内容写入到图形缓冲区中去之后，还需要将图形缓冲区渲染到系统帧缓冲区中去，这样才可以把画面绘制到设备显示屏中去。前面提到，渲染图形缓冲区是由Gralloc模块中的函数&lt;strong&gt;fb_post&lt;/strong&gt;来实现的，这个函数实现在文件hardware/libhardware/modules/gralloc/framebuffer.cpp中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;fb_post&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;framebuffer_device_t&lt;/span&gt;* dev, &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt; buffer)&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;::validate(buffer) &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -EINVAL;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;fb_context_t&lt;/span&gt;* ctx = (&lt;span class=&quot;keyword&quot;&gt;fb_context_t&lt;/span&gt;*)dev;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* hnd = &lt;span class=&quot;keyword&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;*&amp;gt;(buffer);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;private_module_t&lt;/span&gt;* m = &lt;span class=&quot;keyword&quot;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;keyword&quot;&gt;private_module_t&lt;/span&gt;*&amp;gt;(  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            dev-&amp;gt;common.module);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (hnd-&amp;gt;flags &amp;amp; &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;::PRIV_FLAGS_FRAMEBUFFER) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; offset = hnd-&amp;gt;base - m-&amp;gt;framebuffer-&amp;gt;base;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        m-&amp;gt;info.activate = FB_ACTIVATE_VBL;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        m-&amp;gt;info.yoffset = offset / m-&amp;gt;finfo.line_length;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (ioctl(m-&amp;gt;framebuffer-&amp;gt;fd, FBIOPUT_VSCREENINFO, &amp;amp;m-&amp;gt;info) == &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            LOGE(&lt;span class=&quot;string&quot;&gt;&quot;FBIOPUT_VSCREENINFO failed&quot;&lt;/span&gt;);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            m-&amp;gt;base.unlock(&amp;amp;m-&amp;gt;base, buffer);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -errno;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        m-&amp;gt;currentBuffer = buffer;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// If we can&#39;t do the page_flip, just copy the buffer to the front   &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;FIXME:&lt;/span&gt; use copybit HAL instead of memcpy  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;* fb_vaddr;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;* buffer_vaddr;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        m-&amp;gt;base.lock(&amp;amp;m-&amp;gt;base, m-&amp;gt;framebuffer,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                GRALLOC_USAGE_SW_WRITE_RARELY,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, m-&amp;gt;info.xres, m-&amp;gt;info.yres,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;amp;fb_vaddr);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        m-&amp;gt;base.lock(&amp;amp;m-&amp;gt;base, buffer,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                GRALLOC_USAGE_SW_READ_RARELY,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, m-&amp;gt;info.xres, m-&amp;gt;info.yres,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;amp;buffer_vaddr);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;built_in&quot;&gt;memcpy&lt;/span&gt;(fb_vaddr, buffer_vaddr, m-&amp;gt;finfo.line_length * m-&amp;gt;info.yres);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        m-&amp;gt;base.unlock(&amp;amp;m-&amp;gt;base, buffer);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        m-&amp;gt;base.unlock(&amp;amp;m-&amp;gt;base, m-&amp;gt;framebuffer);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）参数buffer用来描述要渲染的图形缓冲区，它指向的必须要是一个private_handle_t结构体，这是通过调用private_handle_t类的静态成员函数validate来验证的。验证通过之后，就可以将参数buffer所描述的一个buffer_handle_t结构体转换成一个private_handle_t结构体hnd。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;参数&lt;strong&gt;*dev&lt;/strong&gt;用来描述在Gralloc模块中的一个fb设备。从前面的内容可以知道，在打开fb设备的时候，Gralloc模块返回给调用者的实际上是一个fb_context_t结构体，因此，这里就可以将参数dev所描述的一个framebuffer_device_t结构体转换成一个&lt;strong&gt;fb_context_t&lt;/strong&gt;结构体ctx。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;参数dev的成员变量&lt;strong&gt;common&lt;/strong&gt;指向了一个&lt;strong&gt;hw_device_t&lt;/strong&gt;结构体，这个结构体的成员变量&lt;strong&gt;module&lt;/strong&gt;指向了一个Gralloc模块。从前面的内容可以知道，一个Gralloc模块是使用一个&lt;strong&gt;private_module_t&lt;/strong&gt;结构体来描述的，因此，我们可以将&lt;strong&gt;dev-&amp;gt;common.moudle&lt;/strong&gt;转换成一个private_module_t结构体m。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）由于private_handle_t结构体hnd所描述的图形缓冲区可能是在系统帧缓冲区分配的，也有可能是内存中分配的，因此，我们分两种情况来讨论图形缓冲区渲染过程。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当private_handle_t结构体hnd所描述的图形缓冲区是在系统帧缓冲区中分配的时候，即这个图形缓冲区的标志值flags的PRIV_FLAGS_FRAMEBUFFER位等于1的时候，我们是不需要将图形缓冲区的内容拷贝到系统帧缓冲区去的，因为我们将内容写入到图形缓冲区的时候，已经相当于是将内容写入到了系统帧缓冲区中去了。虽然在这种情况下，我们不需要将图形缓冲区的内容拷贝到系统帧缓冲区去，但是我们需要告诉系统帧缓冲区设备将要渲染的图形缓冲区作为系统当前的输出图形缓冲区，这样才可以将要渲染的图形缓冲区的内容绘制到设备显示屏来。例如，假设系统帧缓冲区有2个图形缓冲区，当前是以第1个图形缓冲区作为输出图形缓冲区的，这时候如果我们需要渲染第2个图形缓冲区，那么就必须告诉系统帧绘冲区设备，将第2个图形缓冲区作为输出图形缓冲区。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;设置系统帧缓冲区的当前输出图形缓冲区是通过IO控制命令FBIOPUT_VSCREENINFO来进行的。IO控制命令FBIOPUT_VSCREENINFO需要一个fb_var_screeninfo结构体作为参数。从前面的内容可以知道，private_module_t结构体m的成员变量&lt;strong&gt;info&lt;/strong&gt;正好保存在我们所需要的这个fb_var_screeninfo结构体。有了个m-&amp;gt;info这个fb_var_screeninfo结构体之后，我们只需要设置好它的成员变量&lt;strong&gt;yoffset&lt;/strong&gt;的值（不用设置成员变量&lt;strong&gt;xoffset&lt;/strong&gt;的值是因为所有的图形缓冲区的宽度是相等的），就可以将要渲染的图形缓冲区设置为系统帧缓冲区的当前输出图形缓冲区。fb_var_screeninfo结构体的成员变量&lt;strong&gt;yoffset&lt;/strong&gt;保存的是当前输出图形缓冲区在整个系统帧缓冲区的纵向偏移量，即Y偏移量。我们只需要将要渲染的图形缓冲区的开始地址&lt;strong&gt;hnd-&amp;gt;base&lt;/strong&gt;的值减去系统帧缓冲区的基地址&lt;strong&gt;m-&amp;gt;framebuffer-&amp;gt;base&lt;/strong&gt;的值，再除以图形缓冲区一行所占据的字节数&lt;strong&gt;m-&amp;gt;finfo.line_length&lt;/strong&gt;，就可以得到所需要的Y偏移量。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在执行IO控制命令FBIOPUT_VSCREENINFO之前，还会将作为参数的fb_var_screeninfo结构体的成员变量&lt;strong&gt;activate&lt;/strong&gt;的值设置&lt;strong&gt;FB_ACTIVATE_VBL&lt;/strong&gt;，表示要等到下一个垂直同步事件出现时，再将当前要渲染的图形缓冲区的内容绘制出来。这样做的目的是避免出现屏幕闪烁，即避免前后两个图形缓冲区的内容各有一部分同时出现屏幕中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;成功地执行完成IO控制命令FBIOPUT_VSCREENINFO之后，函数还会将当前被渲染的图形缓冲区保存在private_module_t结构体m的成员变量&lt;strong&gt;currentBuffer&lt;/strong&gt;中，以便可以记录当前被渲染的图形缓冲区是哪一个。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;当private_handle_t结构体hnd所描述的图形缓冲区是在内存中分配的时候，即这个图形缓冲区的标志值flags的PRIV_FLAGS_FRAMEBUFFER位等于0的时候，我们就需要将它的内容拷贝到系统帧缓冲区中去了。这个拷贝的工作是通过调用函数&lt;strong&gt;memcpy&lt;/strong&gt;来完成的。在拷贝之前，我们需要&lt;strong&gt;三个参数&lt;/strong&gt;。第一个参数是要渲染的图形缓冲区的起址地址，这个地址保存在参数&lt;strong&gt;buffer&lt;/strong&gt;所指向的一个private_handle_t结构体中。第二个参数是要系统帧缓冲区的基地址，这个地址保存在private_module_t结构体m的成员变量framebuffer所指向的一个private_handle_t结构体中。第三个参数是要拷贝的内容的大小，这个大小就刚好是一个屏幕像素所占据的内存的大小。屏幕高度由m-&amp;gt;info.yres来描述，而一行屏幕像素所占用的字节数由m-&amp;gt;finfo.line_length来描述，将这两者相乘，就可以得到一个屏幕像素所占据的内存的大小。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）在将一块内存缓冲区的内容拷贝到系统帧缓冲区中去之前，需要对这两块缓冲区进行锁定，以保证在拷贝的过程中，这两块缓冲区的内容不会被修改。这个锁定的工作是由Gralloc模块中的函数&lt;strong&gt;gralloc_lock&lt;/strong&gt;来实现的。从前面第1部分的内容可以知道，Gralloc模块中的函数gralloc_lock的地址正好就保存在private_module_t结构体m的成员变量base所描述的一个gralloc_module_t结构体的成员函数lock中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在调用函数gralloc_lock来锁定一块缓冲区之后，还可以通过最后一个输出参数来获得被锁定的缓冲区的开始地址，因此，通过调用函数gralloc_lock来锁定要渲染的图形缓冲区以及系统帧缓冲区，就可以得到前面所需要的第一个和第二个参数。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;将要渲染的图形缓冲区的内容拷贝到系统帧缓冲区之后，就可以解除前面对它们的锁定了，这个解锁的工作是由Gralloc模块中的函数&lt;strong&gt;gralloc_unlock&lt;/strong&gt;来实现的。从前面第1部分的内容可以知道，Gralloc模块中的函数gralloc_unlock的地址正好就保存在private_module_t结构体m的成员变量base所描述的一个gralloc_module_t结构体的成员函数unlock中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这样，一个图形缓冲区的渲染过程就分析完成了。&lt;/p&gt;
&lt;h3 id=&quot;图形缓冲区的锁定和解锁&quot;&gt;&lt;a href=&quot;#图形缓冲区的锁定和解锁&quot; class=&quot;headerlink&quot; title=&quot;图形缓冲区的锁定和解锁&quot;&gt;&lt;/a&gt;图形缓冲区的锁定和解锁&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;为了完整性起见，最后我们再简要分析函数gralloc_lock和gralloc_unlock的实现，以便可以了解一个图形缓冲区的锁定和解锁操作是如何实现的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）图形缓冲区的锁定：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数gralloc_lock实现在文件hardware/libhardware/modules/gralloc/mapper.cpp文件中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;gralloc_lock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* module,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt; handle, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; usage,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; l, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; t, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; w, &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; h,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;** vaddr)&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// this is called when a buffer is being locked for software  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// access. in thin implementation we have nothing to do since  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// not synchronization with the h/w is needed.  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// typically this is used to wait for the h/w to finish with  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// this buffer if relevant. the data cache may need to be  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// flushed or invalidated depending on the usage bits and the  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// hardware.  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;::validate(handle) &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -EINVAL;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;* hnd = (&lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;*)handle;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    *vaddr = (&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt;*)hnd-&amp;gt;base;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从这里可以看出，函数gralloc_lock其实并没有执行锁定参数handle所描述的一个缓冲区的操作，它只简单地将要锁定的缓冲区的开始地址返回给调用者。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;理论上来说，函数gralloc_lock应该检查参数handle所描述的一个缓冲区是否正在被其进程或者线程使用。如果是的话，那么函数gralloc_lock就必须要等待，直到要锁定的缓冲区被其它进程或者线程使用结束为止，以便接下来可以独占它。由于函数gralloc_lock实际上并没有作这些操作，&lt;strong&gt;因此，就必须要由调用者来保证要锁定的缓冲区当前是没有被其它进程或者线程使用的&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）图形缓冲区的解锁：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数gralloc_unlock也是实现在文件hardware/libhardware/modules/gralloc/mapper.cpp文件中，如下所示：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;gralloc_unlock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;gralloc_module_t&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt;* module,  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;buffer_handle_t&lt;/span&gt; handle)&lt;/span&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// we&#39;re done with a software buffer. nothing to do in this  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// implementation. typically this is used to flush the data cache.  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;private_handle_t&lt;/span&gt;::validate(handle) &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; -EINVAL;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;函数gralloc_unlock执行的操作本来是刚好与函数gralloc_lock相反的，但是由于函数gralloc_lock并没有真实地锁定参数handle所描述的一个缓冲区的，因此，函数gralloc_unlock是不需要执行实际的解锁工作的。&lt;/p&gt;
&lt;h1 id=&quot;小结&quot;&gt;&lt;a href=&quot;#小结&quot; class=&quot;headerlink&quot; title=&quot;小结&quot;&gt;&lt;/a&gt;小结&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;至此，我们就分析完成Android帧缓冲区硬件抽象层模块Gralloc的实现原理了。从分析的过程可以知道，为了在屏幕中绘制一个指定的画面，我们需要：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;分配一个匹配屏幕大小的图形缓冲区&lt;/li&gt;
&lt;li&gt;将分配好的图形缓冲区注册（映射）到当前进程的地址空间来&lt;/li&gt;
&lt;li&gt;将要绘制的画面的内容写入到已经注册好的图形缓冲区中去，并且渲染（拷贝）到系统帧缓冲区中去&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;为了实现以上三个操作，我们还需要：&lt;/li&gt;
&lt;li&gt;加载Gralloc模块&lt;/li&gt;
&lt;li&gt;打开Gralloc模块中的gralloc设备和fb设备&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;其中，gralloc设备负责分配图形缓冲区，Gralloc模块负责注册图形缓冲区，而fb设备负责渲染图形缓冲区。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个系列内容还是太多了，我估计坚持不了多久。。。。。另外，求HR或者大神带我入坑，妹子图敬上~&lt;br&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%20SurfaceFlinger%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF%28%E4%B8%80%29----Android%E5%9B%BE%E5%BD%A2%E6%98%BE%E7%A4%BA%E4%B9%8BHAL%E5%B1%82Gralloc%E6%A8%A1%E5%9D%97%E5%AE%9E%E7%8E%B0/meizi.jpg&quot; alt=&quot;妹子&quot;&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;好久没更新了，主要是因为年前和年后太忙了，尤其是年后这一段时间，忙得把身体都忙坏了。。。。。。终于在我GG之前，提交了离职，总算赢得了一些空闲时间，赶紧养养身体。。。现在处于即将待业状态，正好有时间研究一下年前就想了解的surfaceflinger模块。。。不过最近我也看了下，surfaceflinger内容太多太复杂了，&lt;code&gt;也许这个系列我坚持不了多久&lt;/code&gt;，不能像上一个MediaPlayer系列那样。。。。。。&lt;code&gt;同时，因为目前我处于即将待业状况，所以求好心HR或者大牛带我入新坑，感激不尽(~ToT~)&lt;/code&gt;&lt;br&gt;
    
    </summary>
    
      <category term="Android技术点" scheme="http://windrunnerlihuan.com/categories/Android%E6%8A%80%E6%9C%AF%E7%82%B9/"/>
    
    
      <category term="SurfaceFlinger" scheme="http://windrunnerlihuan.com/tags/SurfaceFlinger/"/>
    
  </entry>
  
  <entry>
    <title>Android多媒体开发(九)----Video Buffer传输与Audio Playback流程</title>
    <link href="http://windrunnerlihuan.com/2017/01/13/Android%E5%A4%9A%E5%AA%92%E4%BD%93%E5%BC%80%E5%8F%91-%E4%B9%9D-Video-Buffer%E4%BC%A0%E8%BE%93%E4%B8%8EAudio-Playback%E6%B5%81%E7%A8%8B/"/>
    <id>http://windrunnerlihuan.com/2017/01/13/Android多媒体开发-九-Video-Buffer传输与Audio-Playback流程/</id>
    <published>2017-01-13T10:28:15.000Z</published>
    <updated>2019-01-06T07:24:48.146Z</updated>
    
    <content type="html">&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上一篇我们简要分析了一下播放流程，主要讲了音频、视频播放和音视频同步的问题。但是对于视频读取buffer还有音频start之后发生的流程都没有分析。本节我们就这两点再分析一番。&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;Video-Buffer传输流程&quot;&gt;&lt;a href=&quot;#Video-Buffer传输流程&quot; class=&quot;headerlink&quot; title=&quot;Video Buffer传输流程&quot;&gt;&lt;/a&gt;Video Buffer传输流程&lt;/h1&gt;&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%E5%A4%9A%E5%AA%92%E4%BD%93%E5%BC%80%E5%8F%91%28%E4%B9%9D%29----Video%20Buffer%E4%BC%A0%E8%BE%93%E4%B8%8EAudio%20Playback%E6%B5%81%E7%A8%8B/videobuffer.jpg&quot; alt=&quot;video buffer&quot;&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上一节的play流程中，OMXCodec会在一开始的时候透过read函数来传送未解码的data给decoder，并要求decoder将解码后的data传回来。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们看看OMXCodec的read方法，位于framework/av/media/libstagefright/OMXCodec.cpp：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; OMXCodec::read(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        MediaBuffer **buffer, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; ReadOptions *options) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = OK;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    *buffer = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;autoLock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mLock)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//状态已经置为EXECUTING &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mState != EXECUTING &amp;amp;&amp;amp; mState != RECONFIGURING) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; UNKNOWN_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; seeking = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int64_t&lt;/span&gt; seekTimeUs;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ReadOptions::SeekMode seekMode;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果有seek，则要设置一下seek相关参数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (options &amp;amp;&amp;amp; options-&amp;gt;getSeekTo(&amp;amp;seekTimeUs, &amp;amp;seekMode)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        seeking = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//这个mInitialBufferSubmit默认为true,第一次会进来&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mInitialBufferSubmit) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mInitialBufferSubmit = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (seeking) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            CHECK(seekTimeUs &amp;gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSeekTimeUs = seekTimeUs;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSeekMode = seekMode;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// There&#39;s no reason to trigger the code below, there&#39;s&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// nothing to flush yet.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            seeking = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mPaused = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//这个很重要：读取需要解码的data，并送往omx解码&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        drainInputBuffers();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mState == EXECUTING) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// Otherwise mState == RECONFIGURING and this code will trigger&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// after the output port is reenabled.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//这个也很重要：从输入端口读取解码好的data&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            fillOutputBuffers();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (seeking) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       ...省略seek相关处理，这个不重要...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//当输出缓冲区mFilledBuffers为空时会等待解码器解码并填充数据，如果有数据，则直接取走数据&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (mState != ERROR &amp;amp;&amp;amp; !mNoMoreOutputData &amp;amp;&amp;amp; mFilledBuffers.empty()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((err = waitForBufferFilled_l()) != OK) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//状态出错&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mState == ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; UNKNOWN_ERROR;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果输出缓冲区为空，判断是否是文件结尾&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mFilledBuffers.empty()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mSignalledEOS ? mFinalStatus : ERROR_END_OF_STREAM;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//判断输入端口设置是否发生了变化&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mOutputPortSettingsHaveChanged) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mOutputPortSettingsHaveChanged = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; INFO_FORMAT_CHANGED;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*这里我们将输出缓冲区中的bufferinfo取出来，并将其中的mediabuffer赋值给传递进来的参数buffer*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;/*当decoder解码出来数据后会将存放数据的buffer放在mFilledBuffers中，因此audioplayer每次从omxcodec读取数据时，会从mFilledBuffers中取*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; index = *mFilledBuffers.begin();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFilledBuffers.erase(mFilledBuffers.begin());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BufferInfo *info = &amp;amp;mPortBuffers[kPortIndexOutput].editItemAt(index);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    CHECK_EQ((&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;)info-&amp;gt;mStatus, (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;)OWNED_BY_US);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//说明此info归client所有，client释放后会归还的&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    info-&amp;gt;mStatus = OWNED_BY_CLIENT;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//info-&amp;gt;mMediaBuffer-&amp;gt;add_ref();是增加一个引用，估计release的时候用~~&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    info-&amp;gt;mMediaBuffer-&amp;gt;add_ref();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mSkipCutBuffer != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSkipCutBuffer-&amp;gt;submit(info-&amp;gt;mMediaBuffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    *buffer = info-&amp;gt;mMediaBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; OK;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个流程比较长，我们分步来看：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）设置相关参数。前面设置好参数mState 后，会经过几次回调将状态设置成EXECUTING，不会return；获取seek的拖动进度，拿到时间戳等，更改拖动参数变量。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）&lt;strong&gt;解封装读取数据，送往omx解码组件解码，并返回解码后的数据&lt;/strong&gt;。（这一部分是整个流程的核心，我们接下来会讲到）&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//省略后相关代码如下&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mInitialBufferSubmit) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       mInitialBufferSubmit = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        drainInputBuffers();  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      fillOutputBuffers();  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里需要注意的是mInitialBufferSubmit默认是true。drainInputBuffers可以认为从extractor读取一包数据。fillOutputBuffers是解码一包数据并放在输出buffer中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）将输出缓冲区中的bufferinfo取出来，并将其中的mediabuffer赋值给传递进来的参数buffer。&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//省略后相关代码如下&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; index = *mFilledBuffers.begin();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;mFilledBuffers.erase(mFilledBuffers.begin());  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;BufferInfo *info = &amp;amp;mPortBuffers[kPortIndexOutput].editItemAt(index);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;CHECK_EQ((&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;)info-&amp;gt;mStatus, (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;)OWNED_BY_US);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;info-&amp;gt;mStatus = OWNED_BY_CLIENT;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;info-&amp;gt;mMediaBuffer-&amp;gt;add_ref();  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mSkipCutBuffer != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mSkipCutBuffer-&amp;gt;submit(info-&amp;gt;mMediaBuffer);  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &amp;#125;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; *buffer = info-&amp;gt;mMediaBuffer;  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; OK;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里我们将输出缓冲区中的bufferinfo取出来，并将其中的mediabuffer赋值给传递进来的参数buffer，当decoder解码出来数据后会将存放数据的buffer放在mFilledBuffers中，因此每次从omxcodec读取数据时，会从mFilledBuffers中取。区别在于，当mFilledBuffers为空时会等待解码器解码并填充数据，如果有数据，则直接取走数据。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;在读取这一步之前，将info-&amp;gt;mStatus 已经设置为OWNED_BY_CLIENT，说明此info归client所有，client释放后会归还的。&lt;/strong&gt;&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;通过设置mStatus可以让这一块内存由不同的模块来支配，如其角色有如下几个：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;enum&lt;/span&gt; BufferStatus &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    OWNED_BY_US,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    OWNED_BY_COMPONENT,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    OWNED_BY_NATIVE_WINDOW,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    OWNED_BY_CLIENT,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;显然component是解码器的，client是外部的。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;info-&amp;gt;mMediaBuffer-&amp;gt;add_ref();是增加一个引用，估计release的时候用~~&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;下面着重分析下如何从extractor读数据，和如何解码数据。&lt;/p&gt;
&lt;h2 id=&quot;drainInputBuffers实现&quot;&gt;&lt;a href=&quot;#drainInputBuffers实现&quot; class=&quot;headerlink&quot; title=&quot;drainInputBuffers实现&quot;&gt;&lt;/a&gt;drainInputBuffers实现&lt;/h2&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;先找到这个方法：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; OMXCodec::drainInputBuffers() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    CHECK(mState == EXECUTING || mState == RECONFIGURING);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//DRM相关，忽略&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mFlags &amp;amp; kUseSecureInputBuffers) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Vector&amp;lt;BufferInfo&amp;gt; *buffers = &amp;amp;mPortBuffers[kPortIndexInput];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; buffers-&amp;gt;size(); ++i) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!drainAnyInputBuffer()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    || (mFlags &amp;amp; kOnlySubmitOneInputBufferAtOneTime)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//kPortIndexInput为0，kPortIndexOutput为1，一个输入一个输出&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Vector&amp;lt;BufferInfo&amp;gt; *buffers = &amp;amp;mPortBuffers[kPortIndexInput];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//我们可能申请了多个输入缓冲区，因此是一个循环&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; buffers-&amp;gt;size(); ++i) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            BufferInfo *info = &amp;amp;buffers-&amp;gt;editItemAt(i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//先检查我们有没有权限使用即OWNED_BY_US&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (info-&amp;gt;mStatus != OWNED_BY_US) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!drainInputBuffer(info)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//kOnlySubmitOneInputBufferAtOneTime即每次只允许读一个包，否则循环都读满&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mFlags &amp;amp; kOnlySubmitOneInputBufferAtOneTime) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里解释下，我们可能申请了多个输入缓冲区，因此是一个循环，先检查我们有没有权限使用即OWNED_BY_US，这一缓冲区获取完数据后会检测。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;kOnlySubmitOneInputBufferAtOneTime即每次只允许读一个包，否则循环都读满。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们继续看drainInputBuffer实现。这一段代码很长，我们只能分部贴出分析：&lt;/p&gt;
&lt;h3 id=&quot;Part-1：&quot;&gt;&lt;a href=&quot;#Part-1：&quot; class=&quot;headerlink&quot; title=&quot;Part.1：&quot;&gt;&lt;/a&gt;Part.1：&lt;/h3&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; OMXCodec::drainInputBuffer(BufferInfo *info) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (info != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        CHECK_EQ((&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;)info-&amp;gt;mStatus, (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;)OWNED_BY_US);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mSignalledEOS) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果有未处理的mCodecSpecificData则先mOMX-&amp;gt;emptyBuffer(info-&amp;gt;Buffer,OMX_BUFFERFLAG_CODECCONFIG)处理这些配置数据&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mCodecSpecificDataIndex &amp;lt; mCodecSpecificData.size()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        CHECK(!(mFlags &amp;amp; kUseSecureInputBuffers));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; CodecSpecificData *specific =&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mCodecSpecificData[mCodecSpecificDataIndex];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; size = specific-&amp;gt;mSize;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果是avc/h264或者hevc/h265，则要处理NAL头部&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mMIME) ||&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;             !strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mMIME))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;amp;&amp;amp; !(mQuirks &amp;amp; kWantsNALFragments)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;uint8_t&lt;/span&gt; kNALStartCode[&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;] =&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;#123; &lt;span class=&quot;number&quot;&gt;0x00&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0x00&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0x00&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0x01&lt;/span&gt; &amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            CHECK(info-&amp;gt;mSize &amp;gt;= specific-&amp;gt;mSize + &lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            size += &lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;built_in&quot;&gt;memcpy&lt;/span&gt;(info-&amp;gt;mData, kNALStartCode, &lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;built_in&quot;&gt;memcpy&lt;/span&gt;((&lt;span class=&quot;keyword&quot;&gt;uint8_t&lt;/span&gt; *)info-&amp;gt;mData + &lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                   specific-&amp;gt;mData, specific-&amp;gt;mSize);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            CHECK(info-&amp;gt;mSize &amp;gt;= specific-&amp;gt;mSize);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;built_in&quot;&gt;memcpy&lt;/span&gt;(info-&amp;gt;mData, specific-&amp;gt;mData, specific-&amp;gt;mSize);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mNoMoreOutputData = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        CODEC_LOGV(&lt;span class=&quot;string&quot;&gt;&quot;calling emptyBuffer with codec specific data&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//处理mCodecSpecificData，mOMX-&amp;gt;emptyBuffer我们后面会讲到&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = mOMX-&amp;gt;emptyBuffer(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mNode, info-&amp;gt;mBuffer, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, size,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        CHECK_EQ(err, (&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt;)OK);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        info-&amp;gt;mStatus = OWNED_BY_COMPONENT;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ++mCodecSpecificDataIndex;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mPaused) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...未完，待续...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果有未处理的mCodecSpecificData则先mOMX-&amp;gt;emptyBuffer(info-&amp;gt;Buffer,OMX_BUFFERFLAG_CODECCONFIG)处理这些配置数据。（mOMX-&amp;gt;emptyBuffer我们后边会讲到）&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;如果是avc/h264或者hevc/h265，则要处理NAL头部。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;在H.264/AVC视频编码标准中，整个系统框架被分为了两个层面：视频编码层面（VCL）和网络抽象层面（NAL）。其中，前者负责有效表示视频数据的内容，而后者则负责格式化数据并提供头信息，以保证数据适合各种信道和存储介质上的传输。因此我们平时的每帧数据就是一个NAL单元（SPS与PPS除外）。在实际的H264数据帧中，往往帧前面带有00 00 00 01 或 00 00 01分隔符，一般来说编码器编出的首帧数据为PPS与SPS，接着为I帧……&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;Part-2：&quot;&gt;&lt;a href=&quot;#Part-2：&quot; class=&quot;headerlink&quot; title=&quot;Part.2：&quot;&gt;&lt;/a&gt;Part.2：&lt;/h3&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;96&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;97&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;98&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;99&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;100&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;101&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;102&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;103&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;104&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;105&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;106&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;107&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;108&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;109&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;110&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;111&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;112&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;113&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;114&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;115&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;116&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;117&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;118&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;119&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;120&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;121&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;122&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;123&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;124&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;125&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;126&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;127&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;128&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;129&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;130&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;131&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;132&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;133&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;134&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;135&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;136&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;137&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;138&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;139&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;140&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;141&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;142&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;143&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;144&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;145&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;146&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;147&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;148&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;149&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;150&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;151&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;152&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; OMXCodec::drainInputBuffer(BufferInfo *info) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.1&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; signalEOS = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int64_t&lt;/span&gt; timestampUs = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; offset = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; n = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (;;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        MediaBuffer *srcBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果有seek，处理seek相关&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mSeekTimeUs &amp;gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mLeftOverBuffer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mLeftOverBuffer-&amp;gt;release();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mLeftOverBuffer = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            MediaSource::ReadOptions options;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            options.setSeekTo(mSeekTimeUs, mSeekMode);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSeekTimeUs = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSeekMode = ReadOptions::SEEK_CLOSEST_SYNC;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mBufferFilled.signal();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//这里的mSource是在AwesomePlayer里面设置的mVideoTrack，从extractor读取数据,用于不同数据源的解封装&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            err = mSource-&amp;gt;read(&amp;amp;srcBuffer, &amp;amp;options);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == OK) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;int64_t&lt;/span&gt; targetTimeUs;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (srcBuffer-&amp;gt;meta_data()-&amp;gt;findInt64(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            kKeyTargetTime, &amp;amp;targetTimeUs)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &amp;amp;&amp;amp; targetTimeUs &amp;gt;= &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    CODEC_LOGV(&lt;span class=&quot;string&quot;&gt;&quot;targetTimeUs = %lld us&quot;&lt;/span&gt;, targetTimeUs);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    mTargetTimeUs = targetTimeUs;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    mTargetTimeUs = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mLeftOverBuffer) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//如果是读取溢出了，下面代码会有判断逻辑&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            srcBuffer = mLeftOverBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mLeftOverBuffer = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            err = OK;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//同上，只不过没有seek的进度&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            err = mSource-&amp;gt;read(&amp;amp;srcBuffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != OK) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            signalEOS = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mFinalStatus = err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mSignalledEOS = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mBufferFilled.signal();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//DRM相关，忽略&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mFlags &amp;amp; kUseSecureInputBuffers) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            info = findInputBufferByDataPointer(srcBuffer-&amp;gt;data());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            CHECK(info != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;/*下面是判断从extractor读取到的数据是不是超过了总大小*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//计算输入缓冲区剩余容量大小&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; remainingBytes = info-&amp;gt;mSize - offset;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果剩余容量小于解封装后读取的data大小&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (srcBuffer-&amp;gt;range_length() &amp;gt; remainingBytes) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//如果是每次读取的开始&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (offset == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                CODEC_LOGE(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                     &lt;span class=&quot;string&quot;&gt;&quot;Codec&#39;s input buffers are too small to accomodate &quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                     &lt;span class=&quot;string&quot;&gt;&quot;buffer read from source (info-&amp;gt;mSize = %d, srcLength = %d)&quot;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                     info-&amp;gt;mSize, srcBuffer-&amp;gt;range_length());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//解码申请的输入缓冲区大小太小了，无法容纳解封装读取的数据大小&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//释放读取的data &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                srcBuffer-&amp;gt;release();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                srcBuffer = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//设置错误状态&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                setState(ERROR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mLeftOverBuffer = srcBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; releaseBuffer = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mFlags &amp;amp; kStoreMetaDataInVideoBuffers) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                releaseBuffer = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                info-&amp;gt;mMediaBuffer = srcBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mFlags &amp;amp; kUseSecureInputBuffers) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//DRM，忽略&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// Data in &quot;info&quot; is already provided at this time.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                releaseBuffer = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                CHECK(info-&amp;gt;mMediaBuffer == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                info-&amp;gt;mMediaBuffer = srcBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;span class=&quot;comment&quot;&gt;//将读取到的数据拷贝到申请的读取缓冲区中&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            CHECK(srcBuffer-&amp;gt;data() != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) ;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;built_in&quot;&gt;memcpy&lt;/span&gt;((&lt;span class=&quot;keyword&quot;&gt;uint8_t&lt;/span&gt; *)info-&amp;gt;mData + offset,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    (&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;uint8_t&lt;/span&gt; *)srcBuffer-&amp;gt;data()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        + srcBuffer-&amp;gt;range_offset(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    srcBuffer-&amp;gt;range_length());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//读取，拷贝后，将读取位置偏移量加上读取大小&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        offset += srcBuffer-&amp;gt;range_length();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果是OGG Vobis格式的音频&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!strcasecmp(MEDIA_MIMETYPE_AUDIO_VORBIS, mMIME)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            CHECK(!(mQuirks &amp;amp; kSupportsMultipleFramesPerInputBuffer));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            CHECK_GE(info-&amp;gt;mSize, offset + &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(&lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt;));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;int32_t&lt;/span&gt; numPageSamples;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!srcBuffer-&amp;gt;meta_data()-&amp;gt;findInt32(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        kKeyValidSamples, &amp;amp;numPageSamples)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                numPageSamples = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;built_in&quot;&gt;memcpy&lt;/span&gt;((&lt;span class=&quot;keyword&quot;&gt;uint8_t&lt;/span&gt; *)info-&amp;gt;mData + offset,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                   &amp;amp;numPageSamples,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                   &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(numPageSamples));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            offset += &lt;span class=&quot;keyword&quot;&gt;sizeof&lt;/span&gt;(numPageSamples);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (releaseBuffer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            srcBuffer-&amp;gt;release();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            srcBuffer = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//读取次数，读了几帧&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ++n;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果不支持每次读取多帧，则一次就直接跳出&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!(mQuirks &amp;amp; kSupportsMultipleFramesPerInputBuffer)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//处理本次读取时间&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;int64_t&lt;/span&gt; coalescedDurationUs = lastBufferTimeUs - timestampUs;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//如果时间超过250毫秒则舍弃&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (coalescedDurationUs &amp;gt; &lt;span class=&quot;number&quot;&gt;250000l&lt;/span&gt;l) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// Don&#39;t coalesce more than 250ms worth of encoded data at once.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...未完，待续...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;Part2的代码虽然多，但核心不多。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）从extractor读取数据，用于不同数据源的解封装。这里的mSource是在AwesomePlayer里面设置的mVideoTrack，我们可以回到以前设置数据源那里查看，如果不记得了可回顾一下以前的&lt;a href=&quot;http://windrunnerlihuan.com/2016/12/12/Android%E5%A4%9A%E5%AA%92%E4%BD%93%E5%BC%80%E5%8F%91-%E5%9B%9B-AwesomePlayer%E6%95%B0%E6%8D%AE%E6%BA%90%E5%A4%84%E7%90%86/#网络类型数据源&quot;&gt;Android多媒体开发(四)—-AwesomePlayer数据源处理&lt;/a&gt;。我们假设是MEDIA_MIMETYPE_CONTAINER_MPEG2TS封装格式，取得它的视频流信息，我们要查看MPEG2TSExtractor这个类的getTrack函数，位于frameworks/av/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sp&amp;lt;MediaSource&amp;gt; MPEG2TSExtractor::getTrack(&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; index) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (index &amp;gt;= mSourceImpls.size()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; seekable = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mSourceImpls.size() &amp;gt; &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        CHECK_EQ(mSourceImpls.size(), &lt;span class=&quot;number&quot;&gt;2u&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        sp&amp;lt;MetaData&amp;gt; meta = mSourceImpls.editItemAt(index)-&amp;gt;getFormat();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; *mime;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        CHECK(meta-&amp;gt;findCString(kKeyMIMEType, &amp;amp;mime));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!strncasecmp(&lt;span class=&quot;string&quot;&gt;&quot;audio/&quot;&lt;/span&gt;, mime, &lt;span class=&quot;number&quot;&gt;6&lt;/span&gt;)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            seekable = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; MPEG2TSSource(&lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;, mSourceImpls.editItemAt(index), seekable);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;要解封装读取数据，是MPEG2TSSource的read方法：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; MPEG2TSSource::read(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        MediaBuffer **out, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; ReadOptions *options) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    *out = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;int64_t&lt;/span&gt; seekTimeUs;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ReadOptions::SeekMode seekMode;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mSeekable &amp;amp;&amp;amp; options &amp;amp;&amp;amp; options-&amp;gt;getSeekTo(&amp;amp;seekTimeUs, &amp;amp;seekMode)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; ERROR_UNSUPPORTED;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; finalResult;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (!mImpl-&amp;gt;hasBufferAvailable(&amp;amp;finalResult)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (finalResult != OK) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; ERROR_END_OF_STREAM;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = mExtractor-&amp;gt;feedMore();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != OK) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mImpl-&amp;gt;signalEOS(err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; mImpl-&amp;gt;read(out, options);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;不过遗憾的是这里涉及MPEG-TS文件格式问题，并且上述read方法主要是使用mImpl来实现的。由于文件格式比较复杂，这里就止步了，有兴趣的同学可以下去自行研究。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）判断从extractor读取到的数据是不是超过了总大小 。先计算申请的缓冲区剩余容量，然后根据上一步读取的大小和她进行比大小，从而判断是否读取溢出。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）将读取的数据拷贝进申请的读入缓冲区中。这里读取完毕后将缓冲区的状态设置成OWNED_BY_COMPONENT 解码器就可以解码了。这里可以看出来读取数据时实现了一次拷贝~~，而不是用的同一块缓冲区(省略一些细节)&lt;/p&gt;
&lt;h3 id=&quot;Part-3&quot;&gt;&lt;a href=&quot;#Part-3&quot; class=&quot;headerlink&quot; title=&quot;Part.3&quot;&gt;&lt;/a&gt;Part.3&lt;/h3&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; OMXCodec::drainInputBuffer(BufferInfo *info) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.1&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...Part&lt;span class=&quot;number&quot;&gt;.2&lt;/span&gt;...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (n &amp;gt; &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGV(&lt;span class=&quot;string&quot;&gt;&quot;coalesced %d frames into one input buffer&quot;&lt;/span&gt;, n);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (signalEOS) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        flags |= OMX_BUFFERFLAG_EOS;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mNoMoreOutputData = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//将解封装的数据送往OMX去解码&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    err = mOMX-&amp;gt;emptyBuffer(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mNode, info-&amp;gt;mBuffer, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, offset,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            flags, timestampUs);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != OK) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        setState(ERROR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    info-&amp;gt;mStatus = OWNED_BY_COMPONENT;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里读取完毕后将缓冲区的状态设置成OWNED_BY_COMPONENT 解码器就可以解码了。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;下面看读取数据完毕后调用mOMX-&amp;gt;emptyBuffer都干了些啥。位于frameworks/av/media/libstagefright/omx/OMX.cpp中&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; OMX::emptyBuffer(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        node_id node,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        buffer_id buffer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OMX_U32 range_offset, OMX_U32 range_length,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OMX_U32 flags, OMX_TICKS timestamp) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; findInstance(node)-&amp;gt;emptyBuffer(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            buffer, range_offset, range_length, flags, timestamp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;然后根绝node节点找到自己的OMXNodeInstance，找到emptyBuffer方法，位于frameworks/av/media/libstagefright/omx/OMXNodeInstance.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; OMXNodeInstance::emptyBuffer(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OMX::buffer_id buffer,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OMX_U32 rangeOffset, OMX_U32 rangeLength,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OMX_U32 flags, OMX_TICKS timestamp) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;autoLock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mLock)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    header-&amp;gt;nFilledLen = rangeLength;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    header-&amp;gt;nOffset = rangeOffset;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    header-&amp;gt;nFlags = flags;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    header-&amp;gt;nTimeStamp = timestamp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    BufferMeta *buffer_meta =&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;BufferMeta *&amp;gt;(header-&amp;gt;pAppPrivate);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    buffer_meta-&amp;gt;CopyToOMX(header);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//此处mHandle对应相应解码组件的&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; StatusFromOMXError(err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这时候就是调用OMX的方法了，我们在&lt;a href=&quot;http://windrunnerlihuan.com/2016/12/29/Android%E5%A4%9A%E5%AA%92%E4%BD%93%E5%BC%80%E5%8F%91-%E4%B8%83-Android%E4%B8%ADOpenMax%E7%9A%84%E5%AE%9E%E7%8E%B0/&quot;&gt;Android多媒体开发(七)—-Android中OpenMax的实现&lt;/a&gt; 讲过，OMX适配层会去查找匹配的相应解码组件，如果忘掉的可以查看这这一节。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;以前我们分析的都是硬解，比如高通、TI的平台，但这里我们为了更清晰分析这个流程，我们选择软解组件，及OMX.google.XX.XX.Decoder。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们假设视频编码格式hevc/h265的，因此找到对应的软解组件SoftHEVC，位于frameworks/av/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp。但是我们没有找到emptyThisBuffer方法，所以得去它父类的父类SimpleSoftOMXComponent中去查找，位于frameworks/av/media/libstagefright/omx/SimpleSoftOMXComponent.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;OMX_ERRORTYPE SimpleSoftOMXComponent::emptyThisBuffer(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OMX_BUFFERHEADERTYPE *buffer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;AMessage&amp;gt; msg = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; AMessage(kWhatEmptyThisBuffer, mHandler-&amp;gt;id());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    msg-&amp;gt;setPointer(&lt;span class=&quot;string&quot;&gt;&quot;header&quot;&lt;/span&gt;, buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    msg-&amp;gt;post();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; OMX_ErrorNone;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;可以看到就是发了一条命令kWhatEmptyThisBuffer，通过handler-&amp;gt;id确定了自己发的还得自己收，处理函数如下：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SimpleSoftOMXComponent::onMessageReceived(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;AMessage&amp;gt; &amp;amp;msg) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;autoLock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mLock)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;uint32_t&lt;/span&gt; msgType = msg-&amp;gt;what();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGV(&lt;span class=&quot;string&quot;&gt;&quot;msgType = %d&quot;&lt;/span&gt;, msgType);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt; (msgType) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; kWhatEmptyThisBuffer:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; kWhatFillThisBuffer:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            OMX_BUFFERHEADERTYPE *header;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            CHECK(msg-&amp;gt;findPointer(&lt;span class=&quot;string&quot;&gt;&quot;header&quot;&lt;/span&gt;, (&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; **)&amp;amp;header));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            CHECK(mState == OMX_StateExecuting &amp;amp;&amp;amp; mTargetState == mState);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; found = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; portIndex = (kWhatEmptyThisBuffer == msgType)?&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    header-&amp;gt;nInputPortIndex: header-&amp;gt;nOutputPortIndex;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            PortInfo *port = &amp;amp;mPorts.editItemAt(portIndex);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; j = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; j &amp;lt; port-&amp;gt;mBuffers.size(); ++j) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                BufferInfo *buffer = &amp;amp;port-&amp;gt;mBuffers.editItemAt(j);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (buffer-&amp;gt;mHeader == header) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    CHECK(!buffer-&amp;gt;mOwnedByUs);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    buffer-&amp;gt;mOwnedByUs = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    CHECK((msgType == kWhatEmptyThisBuffer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            &amp;amp;&amp;amp; port-&amp;gt;mDef.eDir == OMX_DirInput)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            || (port-&amp;gt;mDef.eDir == OMX_DirOutput));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    port-&amp;gt;mQueue.push_back(buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    onQueueFilled(portIndex);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    found = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            CHECK(found);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;default&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            TRESPASS();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;从代码这里来看这两个case都走同一套代码，而且都是通过onQueueFilled来处理，这样我们就引出了实际的处理函数，也就是onQueueFilled。此时我们就得去子类SoftHEVC.cpp中查找：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;94&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SoftHEVC::onQueueFilled(OMX_U32 portIndex) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    UNUSED(portIndex);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mOutputPortSettingsChange != NONE) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//获取输入输出链表 &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    List&amp;lt;BufferInfo *&amp;gt; &amp;amp;inQueue = getPortQueue(kInputPortIndex);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    List&amp;lt;BufferInfo *&amp;gt; &amp;amp;outQueue = getPortQueue(kOutputPortIndex);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (!outQueue.empty()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//输入缓冲区&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        BufferInfo *inInfo;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OMX_BUFFERHEADERTYPE *inHeader;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//输出缓冲区&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        BufferInfo *outInfo;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OMX_BUFFERHEADERTYPE *outHeader;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; timeStampIx;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        inInfo = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        inHeader = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//各自取输入输出缓冲区中的第一个缓冲区  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        outInfo = *outQueue.begin();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        outHeader = outInfo-&amp;gt;mHeader;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        outHeader-&amp;gt;nFlags = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        outHeader-&amp;gt;nTimeStamp = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        outHeader-&amp;gt;nOffset = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//判断缓冲区是不是没有数据，若果第一个都没有那就是没有 &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (inHeader != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt; &amp;amp;&amp;amp; (inHeader-&amp;gt;nFlags &amp;amp; OMX_BUFFERFLAG_EOS)) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ALOGD(&lt;span class=&quot;string&quot;&gt;&quot;EOS seen on input&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mReceivedEOS = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (inHeader-&amp;gt;nFilledLen == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                inQueue.erase(inQueue.begin());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                inInfo-&amp;gt;mOwnedByUs = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//如果输入缓冲区数据没有了，则调用notifyEmptyBufferDone &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                notifyEmptyBufferDone(inHeader);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                inHeader = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                setFlushMode();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;/***************************省略解码相关细节******************************/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (s_dec_op.u4_output_present) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                outHeader-&amp;gt;nFilledLen = (mWidth * mHeight * &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;) / &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                outHeader-&amp;gt;nTimeStamp = mTimeStamps[s_dec_op.u4_ts];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mTimeStampsValid[s_dec_op.u4_ts] = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                outInfo-&amp;gt;mOwnedByUs = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                outQueue.erase(outQueue.begin());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                outInfo = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//这是将解码出来的数据告诉外部，通过调用notifyFillBufferDone &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                notifyFillBufferDone(outHeader);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                outHeader = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;/* If in flush mode and no output is returned by the codec,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                 * then come out of flush mode */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mIsInFlush = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;/* If EOS was recieved on input port and there is no output&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                 * from the codec, then signal EOS on output port */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mReceivedEOS) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    outHeader-&amp;gt;nFilledLen = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    outHeader-&amp;gt;nFlags |= OMX_BUFFERFLAG_EOS;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    outInfo-&amp;gt;mOwnedByUs = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    outQueue.erase(outQueue.begin());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    outInfo = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//这是将解码出来的数据告诉外部，通过调用notifyFillBufferDone &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    notifyFillBufferDone(outHeader);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    outHeader = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    resetPlugin();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// &lt;span class=&quot;doctag&quot;&gt;TODO:&lt;/span&gt; Handle more than one picture data&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (inHeader != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            inInfo-&amp;gt;mOwnedByUs = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            inQueue.erase(inQueue.begin());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            inInfo = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// 如果输入缓冲区数据都解码完了，则调用notifyEmptyBufferDone &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            notifyEmptyBufferDone(inHeader);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            inHeader = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;以上就是输入缓冲区数据解码再从输出缓冲区传递出去部分。流程大概是：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）读取输入缓冲区数据，如果空了则表示结束了，则调用notifyEmptyBufferDone，输入部分清空；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）如果读取到了数据，则送去解码（因为这里设计编码格式等等，因此省略解码细节）；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）然后将解码出来的数据告诉外部，通过调用notifyFillBufferDone ；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;4）循环上述过程。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;所以上述过程的重点就是notifyEmptyBufferDone 和notifyFillBufferDone ，如何将输入缓冲区释放和将输出缓冲区中的数据传递出去。接下来我们分析这两个过程。&lt;/p&gt;
&lt;h3 id=&quot;输入部分的清空notifyEmptyBufferDone&quot;&gt;&lt;a href=&quot;#输入部分的清空notifyEmptyBufferDone&quot; class=&quot;headerlink&quot; title=&quot;输入部分的清空notifyEmptyBufferDone&quot;&gt;&lt;/a&gt;输入部分的清空notifyEmptyBufferDone&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;notifyEmptyBufferDone位于它父类的父类的父类，位于frameworks/av/media/libstagefright/omx/SoftOMXComponent.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SoftOMXComponent::notifyEmptyBufferDone(OMX_BUFFERHEADERTYPE *header) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    (*mCallbacks-&amp;gt;EmptyBufferDone)(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mComponent, mComponent-&amp;gt;pApplicationPrivate, header);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;我们在&lt;a href=&quot;http://windrunnerlihuan.com/2016/12/29/Android%E5%A4%9A%E5%AA%92%E4%BD%93%E5%BC%80%E5%8F%91-%E4%B8%83-Android%E4%B8%ADOpenMax%E7%9A%84%E5%AE%9E%E7%8E%B0/&quot;&gt;Android多媒体开发(七)—-Android中OpenMax的实现&lt;/a&gt; 讲过，这里最后还是会回到OMXNodeInstance。通知外面我们emptythisbuffer完工了，具体回调的是OMXNodeInstance中的方法OnEmptyBufferDone，所以看看它的实现：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// static&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OMX_IN OMX_HANDLETYPE &lt;span class=&quot;comment&quot;&gt;/* hComponent */&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OMX_IN OMX_PTR pAppData,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    OMXNodeInstance *instance = &lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;OMXNodeInstance *&amp;gt;(pAppData);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (instance-&amp;gt;mDying) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; OMX_ErrorNone;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; instance-&amp;gt;owner()-&amp;gt;OnEmptyBufferDone(instance-&amp;gt;nodeID(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            instance-&amp;gt;findBufferID(pBuffer), pBuffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;OMXNodeInstance的ownner是OMX，因此代码在OMX.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;OMX_ERRORTYPE OMX::OnEmptyBufferDone(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGV(&lt;span class=&quot;string&quot;&gt;&quot;OnEmptyBufferDone buffer=%p&quot;&lt;/span&gt;, pBuffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    omx_message msg;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    msg.type = omx_message::EMPTY_BUFFER_DONE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    msg.node = node;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    msg.u.buffer_data.buffer = buffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    findDispatcher(node)-&amp;gt;post(msg);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; OMX_ErrorNone;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;其中findDispatcher定义如下:&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sp&amp;lt;OMX::CallbackDispatcher&amp;gt; OMX::findDispatcher(node_id node) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;autoLock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(mLock)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;ssize_t&lt;/span&gt; index = mDispatchers.indexOfKey(node);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; index &amp;lt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; ? &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt; : mDispatchers.valueAt(index);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这里mDispatcher在之前allocateNode中通过mDispatchers.add(*node, new CallbackDispatcher(instance)); 创建的,看下实际的实现可知道，CallbackDispatcher的post方法最终会调用dispatch：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; OMX::CallbackDispatcher::dispatch(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; omx_message &amp;amp;msg) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mOwner == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGV(&lt;span class=&quot;string&quot;&gt;&quot;Would have dispatched a message to a node that&#39;s already gone.&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mOwner-&amp;gt;onMessage(msg);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;而owner是OMXNodeInstance，因此消息饶了一圈还是到了OMXNodeInstance的OnMessage方法接收了:&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; OMXNodeInstance::onMessage(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; omx_message &amp;amp;msg) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; sp&amp;lt;GraphicBufferSource&amp;gt;&amp;amp; bufferSource(getGraphicBufferSource());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (msg.type == omx_message::FILL_BUFFER_DONE) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (msg.type == omx_message::EMPTY_BUFFER_DONE) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (bufferSource != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// This is one of the buffers used exclusively by&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// GraphicBufferSource.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// Don&#39;t dispatch a message back to ACodec, since it doesn&#39;t&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// know that anyone asked to have the buffer emptied and will&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// be very confused.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            OMX_BUFFERHEADERTYPE *buffer =&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                findBufferHeader(msg.u.buffer_data.buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            bufferSource-&amp;gt;codecBufferEmptied(buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mObserver-&amp;gt;onMessage(msg);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;而onMessage又将消息传递到 mObserver中，也就是在OMXCodec::Create中构造的OMXCodecObserver对象，其OnMessage实现如下:&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// from IOMXObserver&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;onMessage&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; omx_message &amp;amp;msg)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sp&amp;lt;OMXCodec&amp;gt; codec = mTarget.promote();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (codec.get() != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Mutex::&lt;span class=&quot;function&quot;&gt;Autolock &lt;span class=&quot;title&quot;&gt;autoLock&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(codec-&amp;gt;mLock)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        codec-&amp;gt;on_message(msg);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        codec.clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;最终还是传递给了OMXCodec里，具体看下：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; OMXCodec::on_message(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; omx_message &amp;amp;msg) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mState == ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;         * only drop EVENT messages, EBD and FBD are still&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;         * processed for bookkeeping purposes&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;         */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (msg.type == omx_message::EVENT) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ALOGW(&lt;span class=&quot;string&quot;&gt;&quot;Dropping OMX EVENT message - we&#39;re in ERROR state.&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt; (msg.type) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; omx_message::EMPTY_BUFFER_DONE:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            CODEC_LOGV(&lt;span class=&quot;string&quot;&gt;&quot;EMPTY_BUFFER_DONE(buffer: %u)&quot;&lt;/span&gt;, buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Vector&amp;lt;BufferInfo&amp;gt; *buffers = &amp;amp;mPortBuffers[kPortIndexInput];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (i &amp;lt; buffers-&amp;gt;size() &amp;amp;&amp;amp; (*buffers)[i].mBuffer != buffer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ++i;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            CHECK(i &amp;lt; buffers-&amp;gt;size());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; ((*buffers)[i].mStatus != OWNED_BY_COMPONENT) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ALOGW(&lt;span class=&quot;string&quot;&gt;&quot;We already own input buffer %u, yet received &quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                     &lt;span class=&quot;string&quot;&gt;&quot;an EMPTY_BUFFER_DONE.&quot;&lt;/span&gt;, buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            BufferInfo* info = &amp;amp;buffers-&amp;gt;editItemAt(i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            info-&amp;gt;mStatus = OWNED_BY_US;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// Buffer could not be released until empty buffer done is called.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (info-&amp;gt;mMediaBuffer != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//此处虽然调用了info-&amp;gt;mMediaBuffer-&amp;gt;release();但是由于其引用始终大于0，因此不会真正的release&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                info-&amp;gt;mMediaBuffer-&amp;gt;release();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                info-&amp;gt;mMediaBuffer = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mPortStatus[kPortIndexInput] == DISABLING) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                CODEC_LOGV(&lt;span class=&quot;string&quot;&gt;&quot;Port is disabled, freeing buffer %u&quot;&lt;/span&gt;, buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = freeBuffer(kPortIndexInput, i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                CHECK_EQ(err, (&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt;)OK);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mState != ERROR&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &amp;amp;&amp;amp; mPortStatus[kPortIndexInput] != SHUTTING_DOWN) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                CHECK_EQ((&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;)mPortStatus[kPortIndexInput], (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;)ENABLED);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mFlags &amp;amp; kUseSecureInputBuffers) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    drainAnyInputBuffer();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//重点在这里，会调用drainInputBuffer(&amp;amp;buffers-&amp;gt;editItemAt(i));来填充数据&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;//也就是说当我们启动一次解码播放后，会在此处循环读取数和据解码数据。而输出数据在后面的filloutbuffer中。&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    drainInputBuffer(&amp;amp;buffers-&amp;gt;editItemAt(i));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;此处虽然调用了info-&amp;gt;mMediaBuffer-&amp;gt;release();但是由于其引用始终大于0，因此不会真正的release。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;二是当release完毕后，会调用drainInputBuffer(&amp;amp;buffers-&amp;gt;editItemAt(i));来填充数据。也就是说当我们启动一次解码播放后，会在此处循环读取数和据解码数据。而输出数据在后面的filloutbuffer中&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;输入部分的清空notifyEmptyBufferDone就分析完了这部分很绕，但搞清楚就好了，请大家仔细阅读。接着我们分析输出数据的清空notifyFillBufferDone(outHeader)。&lt;/p&gt;
&lt;h3 id=&quot;输出数据的清空notifyFillBufferDone-outHeader&quot;&gt;&lt;a href=&quot;#输出数据的清空notifyFillBufferDone-outHeader&quot; class=&quot;headerlink&quot; title=&quot;输出数据的清空notifyFillBufferDone(outHeader)&quot;&gt;&lt;/a&gt;输出数据的清空notifyFillBufferDone(outHeader)&lt;/h3&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;notifyFillBufferDone同样位于SoftOMXComponent.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; SoftOMXComponent::notifyFillBufferDone(OMX_BUFFERHEADERTYPE *header) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    (*mCallbacks-&amp;gt;FillBufferDone)(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mComponent, mComponent-&amp;gt;pApplicationPrivate, header);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;这个和上一步流程分析方法一样，最后回到OMX的OnFillBufferDone方法：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;OMX_ERRORTYPE OMX::OnFillBufferDone(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ALOGV(&lt;span class=&quot;string&quot;&gt;&quot;OnFillBufferDone buffer=%p&quot;&lt;/span&gt;, pBuffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    omx_message msg;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    msg.type = omx_message::FILL_BUFFER_DONE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    msg.node = node;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    msg.u.extended_buffer_data.buffer = buffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    msg.u.extended_buffer_data.range_offset = pBuffer-&amp;gt;nOffset;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    msg.u.extended_buffer_data.range_length = pBuffer-&amp;gt;nFilledLen;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    msg.u.extended_buffer_data.flags = pBuffer-&amp;gt;nFlags;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    msg.u.extended_buffer_data.timestamp = pBuffer-&amp;gt;nTimeStamp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    findDispatcher(node)-&amp;gt;post(msg);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; OMX_ErrorNone;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;最终处理在OMXCodec.cpp中:&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;96&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; OMXCodec::on_message(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; omx_message &amp;amp;msg) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mState == ERROR) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;/*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;         * only drop EVENT messages, EBD and FBD are still&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;         * processed for bookkeeping purposes&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;         */&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (msg.type == omx_message::EVENT) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ALOGW(&lt;span class=&quot;string&quot;&gt;&quot;Dropping OMX EVENT message - we&#39;re in ERROR state.&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt; (msg.type) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; omx_message::FILL_BUFFER_DONE:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            OMX_U32 flags = msg.u.extended_buffer_data.flags;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            Vector&amp;lt;BufferInfo&amp;gt; *buffers = &amp;amp;mPortBuffers[kPortIndexOutput];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (i &amp;lt; buffers-&amp;gt;size() &amp;amp;&amp;amp; (*buffers)[i].mBuffer != buffer) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ++i;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            CHECK(i &amp;lt; buffers-&amp;gt;size());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            BufferInfo *info = &amp;amp;buffers-&amp;gt;editItemAt(i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (info-&amp;gt;mStatus != OWNED_BY_COMPONENT) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ALOGW(&lt;span class=&quot;string&quot;&gt;&quot;We already own output buffer %u, yet received &quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                     &lt;span class=&quot;string&quot;&gt;&quot;a FILL_BUFFER_DONE.&quot;&lt;/span&gt;, buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//先将mStatus设置成OWNED_BY_US，这样component便不能操作了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            info-&amp;gt;mStatus = OWNED_BY_US;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mPortStatus[kPortIndexOutput] == DISABLING) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                CHECK_EQ((&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;)mPortStatus[kPortIndexOutput], (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;)ENABLED);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                MediaBuffer *buffer = info-&amp;gt;mMediaBuffer;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; isGraphicBuffer = buffer-&amp;gt;graphicBuffer() != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;/*buffer相关参数设置，可以忽略*/&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                buffer-&amp;gt;set_range(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        msg.u.extended_buffer_data.range_offset,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        msg.u.extended_buffer_data.range_length);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                buffer-&amp;gt;meta_data()-&amp;gt;clear();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                buffer-&amp;gt;meta_data()-&amp;gt;setInt64(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        kKeyTime, msg.u.extended_buffer_data.timestamp);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (msg.u.extended_buffer_data.flags &amp;amp; OMX_BUFFERFLAG_SYNCFRAME) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    buffer-&amp;gt;meta_data()-&amp;gt;setInt32(kKeyIsSyncFrame, &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; isCodecSpecific = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (msg.u.extended_buffer_data.flags &amp;amp; OMX_BUFFERFLAG_CODECCONFIG) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    buffer-&amp;gt;meta_data()-&amp;gt;setInt32(kKeyIsCodecConfig, &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    isCodecSpecific = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (isGraphicBuffer || mQuirks &amp;amp; kOutputBuffersAreUnreadable) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    buffer-&amp;gt;meta_data()-&amp;gt;setInt32(kKeyIsUnreadable, &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                buffer-&amp;gt;meta_data()-&amp;gt;setInt32(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        kKeyBufferID,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        msg.u.extended_buffer_data.buffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (msg.u.extended_buffer_data.flags &amp;amp; OMX_BUFFERFLAG_EOS) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    CODEC_LOGV(&lt;span class=&quot;string&quot;&gt;&quot;No more output data.&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    mNoMoreOutputData = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mIsEncoder &amp;amp;&amp;amp; mIsVideo) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;int64_t&lt;/span&gt; decodingTimeUs = isCodecSpecific? &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;: getDecodingTimeUs();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    buffer-&amp;gt;meta_data()-&amp;gt;setInt64(kKeyDecodingTime, decodingTimeUs);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;//核心是下面几句，将这个buffer push到mFilledBuffers中。&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mFilledBuffers.push_back(i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mBufferFilled.signal();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mIsEncoder) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    sched_yield();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上述代码主体也不多：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）先将mStatus设置成OWNED_BY_US，这样component便不能操作了；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）对于解码好的buffer进行相关参数设置；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）后面将这个buffer push到mFilledBuffers中。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;输出数据的清空notifyFillBufferDone就分析完了，这里我们的mFilledBuffers就有数据了，就能为Video Buffer传输流程的下一步fillOutputBuffers做准备了。&lt;/p&gt;
&lt;h2 id=&quot;fillOutputBuffers实现&quot;&gt;&lt;a href=&quot;#fillOutputBuffers实现&quot; class=&quot;headerlink&quot; title=&quot;fillOutputBuffers实现&quot;&gt;&lt;/a&gt;fillOutputBuffers实现&lt;/h2&gt;&lt;p&gt; &amp;#160; &amp;#160; &amp;#160; &amp;#160;回到开始的步骤，OMXCodec的read第一步drainInputBuffers实现完成了数据的解封装和送往OMX去解码，完成后返回给mFilledBuffers。&lt;br&gt; &amp;#160; &amp;#160; &amp;#160; &amp;#160;所以我们这一步fillOutputBuffers就是读取这些返回解码数据。我们先看看fillOutputBuffers函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; OMXCodec::fillOutputBuffers() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    CHECK_EQ((&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;)mState, (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;)EXECUTING);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Vector&amp;lt;BufferInfo&amp;gt; *buffers = &amp;amp;mPortBuffers[kPortIndexOutput];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i &amp;lt; buffers-&amp;gt;size(); ++i) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        BufferInfo *info = &amp;amp;buffers-&amp;gt;editItemAt(i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (info-&amp;gt;mStatus == OWNED_BY_US) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;//找到一个输出缓冲区bufferinfo，启动输出&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            fillOutputBuffer(&amp;amp;buffers-&amp;gt;editItemAt(i));&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt; &amp;#160; &amp;#160; &amp;#160; &amp;#160;找到一个输出缓冲区bufferinfo，启动输出:&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; OMXCodec::fillOutputBuffer(BufferInfo *info) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    CHECK_EQ((&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;)info-&amp;gt;mStatus, (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;)OWNED_BY_US);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    CODEC_LOGV(&lt;span class=&quot;string&quot;&gt;&quot;Calling fillBuffer on buffer %p&quot;&lt;/span&gt;, info-&amp;gt;mBuffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//依旧可以参考上一步的步骤，最后进入解码器组件里面&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = mOMX-&amp;gt;fillBuffer(mNode, info-&amp;gt;mBuffer);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != OK) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        CODEC_LOGE(&lt;span class=&quot;string&quot;&gt;&quot;fillBuffer failed w/ error 0x%08x&quot;&lt;/span&gt;, err);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        setState(ERROR);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    info-&amp;gt;mStatus = OWNED_BY_COMPONENT;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt; &amp;#160; &amp;#160; &amp;#160; &amp;#160;这一步和上面分析过的步骤相同，最后还是会进入解码器的组件内部，依然以hevc/h265为例子。同样还是如下步骤：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;strong&gt;OMXNodeInstance::fillBuffer—-&amp;gt;SimpleSoftOMXComponent::fillThisBuffer—-&amp;gt;SimpleSoftOMXComponent::onMessageReceived—-&amp;gt;SoftHEVC::onQueueFilled。然后通过notifyEmptyBufferDone(inHeader);和notifyFillBufferDone(outHeader);两个函数来推进播放进度。只不过这次我们最后回到了OMXCodec的on_message回到函数，走了FILL_BUFFER_DONE这个case里的notifyFillBufferDone部分，这个我们上一步最后也分析过这个流程了&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt; &amp;#160; &amp;#160; &amp;#160; &amp;#160;到这里我们fillOutputBuffers实现部分也分析完了，主要就是传输输出缓冲区的数据。&lt;/p&gt;
&lt;h1 id=&quot;Video-Buffer传输流程总结&quot;&gt;&lt;a href=&quot;#Video-Buffer传输流程总结&quot; class=&quot;headerlink&quot; title=&quot;Video Buffer传输流程总结&quot;&gt;&lt;/a&gt;Video Buffer传输流程总结&lt;/h1&gt;&lt;p&gt; &amp;#160; &amp;#160; &amp;#160; &amp;#160;如果把这一流程总结一下，详细流程如下：&lt;br&gt; 1 调用OMXCodec:read()&lt;br&gt; 1.1 先读取ReadOptions看看是不是seek&lt;br&gt; 1.2 如果不是seek，则当前mState必须是EXECUTING或者RECONFIGURING&lt;br&gt; 1.3 如果是提交的第一帧，先调用drainInputBuffers()&lt;br&gt; 1.3.1 执行drainInputBuffers()必须是在mState为EXECUTING，RECONFIGURING和FLUSHING的状态&lt;br&gt; 1.3.2 从mPortBuffers[input]里循环取出每个BufferInfo,并对每个info-&amp;gt;mStatus等于OWNED_BY_US的buffer调用drainInputBuffer(info)&lt;br&gt; 1.3.2.1 drainInputBuffer(BufferInfo)要求buffer必须是OWNED_BY_US&lt;br&gt; 1.3.2.2 如果有未处理的mCodecSpecificData则先mOMX-&amp;gt;emptyBuffer(info-&amp;gt;Buffer,OMX_BUFFERFLAG_CODECCONFIG)处理这些配置数据&lt;br&gt; 1.3.2.3 如果mSignalledEOS或者mPaused为true则停止drain并return false&lt;br&gt; 1.3.2.4 循环调用mSource-&amp;gt;read()读取压缩源srcBuffer，读取失败的话则设置mSignalledEOS为true，如果成功则将其copy进info-&amp;gt;mData里去&lt;br&gt; 1.3.2.5 结果是info-&amp;gt;mData里装着从mSource中多次读取出来的数据总和，并将timestampUs设为第一块数据的kKeyTime值&lt;br&gt; 1.3.2.6 设置flags为OMX_BUFFERFLAG_ENDOFFRAME，如果刚才遇到EOS则再并一个OMX_BUFFERFLAG_EOS&lt;br&gt; 1.3.2.7 调用mOMX-&amp;gt;emptyBuffer(mNode, info-&amp;gt;mBuffer, 0, offset,flags, timestampUs);&lt;br&gt; 1.3.2.8 如果emptyBuffer返回OK，则设置info-&amp;gt;mStatus为OWNED_BY_COMPONENT并return true，否则设置mState为ERROR并返回false&lt;br&gt; 1.4 再调用fillOutputBuffers()&lt;br&gt; 1.4.1 执行fillOutputBuffers()必须是在mState为EXECUTING，FLUSHING的状态&lt;br&gt; 1.4.2 从mPortBuffers[output]里循环取出每个BufferInfo,并对每个info-&amp;gt;mStatus等于OWNED_BY_US的buffer调用fillOutputBuffer(info)&lt;br&gt; 1.4.2.1 如果mNoMoreOutputData为true则return&lt;br&gt; 1.4.2.2 如果info-&amp;gt;mMediaBuffer不为空，则取出其中的GraphicBuffer，并调用mNativeWindow-&amp;gt;lockBuffer(mNativeWindow,graphicBuffer)来锁定该buffer，出错则设置mState为ERROR&lt;br&gt; 1.4.2.3 调用mOMX-&amp;gt;fillBuffer(mNode, info-&amp;gt;mBuffer)&lt;br&gt; 1.4.2.4 如果emptyBuffer返回OK，则设置info-&amp;gt;mStatus为OWNED_BY_COMPONENT，否则设置mState为ERROR，最后return&lt;br&gt; 1.5 如果mState不为ERROR，并且mNoMoreOutputData为false,并且mFilledBuffers为空，并且mOutputPortSettingsChangedPending为false的情况下，则调用waitForBufferFilled_l()，让mBufferFilled去wait lock&lt;br&gt; 1.6 从waitForBufferFilled_l()释放出来后，判断mFilledBuffers为空的话，如果mOutputPortSettingsChangedPending为true则去调用之前延迟执行的onPortSettingsChanged（），否则return EOS&lt;br&gt; 1.7 取出mFilledBuffers的第一个buffer，该buffer的mStatus此时必须为OWNED_BY_US&lt;br&gt; 1.8 然后设置其为OWNED_BY_CLIENT，给该buffer的mMediaBuffer-&amp;gt;add_ref()增加一个引用，并把该mMediaBuffer赋值给buffer并返回给AwesomePlayer&lt;/p&gt;
&lt;h1 id=&quot;Audio-Playback-流程（简要分析）&quot;&gt;&lt;a href=&quot;#Audio-Playback-流程（简要分析）&quot; class=&quot;headerlink&quot; title=&quot;Audio Playback 流程（简要分析）&quot;&gt;&lt;/a&gt;Audio Playback 流程（简要分析）&lt;/h1&gt;&lt;p&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%E5%A4%9A%E5%AA%92%E4%BD%93%E5%BC%80%E5%8F%91%28%E4%B9%9D%29----Video%20Buffer%E4%BC%A0%E8%BE%93%E4%B8%8EAudio%20Playback%E6%B5%81%E7%A8%8B/audioplayback.jpg&quot; alt=&quot;audio playback&quot;&gt;&lt;/p&gt;
&lt;p&gt; &amp;#160; &amp;#160; &amp;#160; &amp;#160;从上一篇可以看到，Audio播放是从AudioPlayer的start函数开始，位于frameworks/av/media/libstagefright/AudioPlayer.cpp中：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; AudioPlayer::start(&lt;span class=&quot;keyword&quot;&gt;bool&lt;/span&gt; sourceAlreadyStarted) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//先处理seek操作&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    MediaSource::ReadOptions options;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mSeeking) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        options.setSeekTo(mSeekTimeUs);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mSeeking = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//从mAudioTrack中读取音频数据，read方法我们在将Video Buffer时分析过了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mFirstBufferResult = mSource-&amp;gt;read(&amp;amp;mFirstBuffer, &amp;amp;options);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mFirstBufferResult == INFO_FORMAT_CHANGED) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGV(&lt;span class=&quot;string&quot;&gt;&quot;INFO_FORMAT_CHANGED!!!&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        CHECK(mFirstBuffer == &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mFirstBufferResult = OK;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mIsFirstBuffer = &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mIsFirstBuffer = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...省略一些判断处理... &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;//如果mAudioSink存在，这个我们在setDataSource已经设置过了，位于MediaPlayerService的AudioOutput&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mAudioSink.get() != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//调用AudioOutput的open函数，注意参数里有AudioPlayer::AudioSinkCallback，我们会用到这个回调&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;status_t&lt;/span&gt; err = mAudioSink-&amp;gt;open(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mSampleRate, numChannels, channelMask, audioFormat,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                DEFAULT_AUDIOSINK_BUFFERCOUNT,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;amp;AudioPlayer::AudioSinkCallback,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                (&lt;span class=&quot;keyword&quot;&gt;audio_output_flags_t&lt;/span&gt;)flags,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                useOffload() ? &amp;amp;offloadInfo : &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err == OK) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mLatencyUs = (&lt;span class=&quot;keyword&quot;&gt;int64_t&lt;/span&gt;)mAudioSink-&amp;gt;latency() * &lt;span class=&quot;number&quot;&gt;1000&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            mFrameSize = mAudioSink-&amp;gt;frameSize();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (useOffload()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// If the playback is offloaded to h/w we pass the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// HAL some metadata information&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// We don&#39;t want to do this for PCM because it will be going&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;comment&quot;&gt;// through the AudioFlinger mixer before reaching the hardware&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                sendMetaDataToHal(mAudioSink, format);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            err = mAudioSink-&amp;gt;start();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;// do not alter behavior for non offloaded tracks: ignore start status.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!useOffload()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                err = OK;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (err != OK) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (mFirstBuffer != &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mFirstBuffer-&amp;gt;release();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mFirstBuffer = &lt;span class=&quot;literal&quot;&gt;NULL&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!sourceAlreadyStarted) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                mSource-&amp;gt;stop();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; err;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125; &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &amp;#123;&lt;span class=&quot;comment&quot;&gt;//如果mAudioSink不存在&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//需要创建一个AudioTrack&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mAudioTrack = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; AudioTrack(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT, audioMask,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;comment&quot;&gt;/*frameCount*/&lt;/span&gt;, AUDIO_OUTPUT_FLAG_NONE, &amp;amp;AudioCallback, &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;comment&quot;&gt;/*notificationFrames*/&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ......&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mLatencyUs = (&lt;span class=&quot;keyword&quot;&gt;int64_t&lt;/span&gt;)mAudioTrack-&amp;gt;latency() * &lt;span class=&quot;number&quot;&gt;1000&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mFrameSize = mAudioTrack-&amp;gt;frameSize();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;//然后调用AudioTrack的start函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        mAudioTrack-&amp;gt;start();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mStarted = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mPlaying = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    mPinnedTimeUs = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;ll;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; OK;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;依然是分部查看：&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;1）从mAudioTrack中读取音频数据，read方法我们在将Video Buffer时分析过了；&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;2）如果mAudioSink存在，这个我们在setDataSource已经设置过了，位于MediaPlayerService的AudioOutput，如果忘记了可以查看&lt;a href=&quot;http://windrunnerlihuan.com/2017/01/06/Android%E5%A4%9A%E5%AA%92%E4%BD%93%E5%BC%80%E5%8F%91-%E5%85%AB-%E6%92%AD%E6%94%BE%E6%B5%81%E7%A8%8B/#设置同步时钟&quot;&gt;上一篇&lt;/a&gt;的&lt;strong&gt;设置同步时钟部分&lt;/strong&gt;。&lt;br&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;3）如果mAudioSink不存在，则创建一个AudioTrack，然后start（这一步我们忽略，因为mAudioSink我们在setDataSource已经创建了）。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;AudioPlayer在启动过程中会先去取第一帧解码的资料，并且开启audio output。这个过程和video buffer很相似。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;开启audio output的同时，AudioPlayer会将callback回调函数指针设给他，之后每次callback函数都被回调，AudioPlayer便去audio decoder读取解码后的数据。我们可以看看这个回调函数：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// static&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; AudioPlayer::AudioCallback(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; event, &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; *user, &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; *info) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;static_cast&lt;/span&gt;&amp;lt;AudioPlayer *&amp;gt;(user)-&amp;gt;AudioCallback(event, info);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// static&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; AudioPlayer::AudioSinkCallback(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        MediaPlayerBase::AudioSink * &lt;span class=&quot;comment&quot;&gt;/* audioSink */&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; *buffer, &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; size, &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; *cookie,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        MediaPlayerBase::AudioSink::&lt;span class=&quot;keyword&quot;&gt;cb_event_t&lt;/span&gt; event) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    AudioPlayer *me = (AudioPlayer *)cookie;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt;(event) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; me-&amp;gt;fillBuffer(buffer, size);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGV(&lt;span class=&quot;string&quot;&gt;&quot;AudioSinkCallback: stream end&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        me-&amp;gt;mReachedEOS = &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        me-&amp;gt;notifyAudioEOS();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt; MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        ALOGV(&lt;span class=&quot;string&quot;&gt;&quot;AudioSinkCallback: Tear down event&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        me-&amp;gt;mObserver-&amp;gt;postAudioTearDown();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上面两个回调分别对应上一步的mAudioSink存在和不存在的情况。但是最后都会调用到自己的fillBuffer方法，我们继续查看(省略大部分逻辑)：&lt;br&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; AudioPlayer::fillBuffer(&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; *data, &lt;span class=&quot;keyword&quot;&gt;size_t&lt;/span&gt; size) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...省略大部分逻辑...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    err = mSource-&amp;gt;read(&amp;amp;mInputBuffer, &amp;amp;options);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...省略大部分逻辑...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;built_in&quot;&gt;memcpy&lt;/span&gt;((&lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; *)data + size_done,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;               (&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;char&lt;/span&gt; *)mInputBuffer-&amp;gt;data() + mInputBuffer-&amp;gt;range_offset(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;               copy);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;解码后audio数据的读取就是有callback回调函数所驱动。另一方面，fillBuffer数据(mInputBuffer)复制到data之后，audio output会去取这些data。&lt;/p&gt;
&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;至于audio decoder的工作流程和video decoder相同，可以参照上面的video buffer流程。&lt;/p&gt;
&lt;h1 id=&quot;结语&quot;&gt;&lt;a href=&quot;#结语&quot; class=&quot;headerlink&quot; title=&quot;结语&quot;&gt;&lt;/a&gt;结语&lt;/h1&gt;&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;本节的重点其实是Video Buffer传输流程，它重点是输入缓冲区释放和将输出缓冲区中的数据传递出去。也算马马虎虎的，请恕我对多媒体的了解也是个未入门的渣渣，还正在自学途中，如有错误麻烦大家及时指出，我会在第一时间修正。&lt;br&gt;&lt;img src=&quot;http://images.windrunnerlihuan.com/img/windrunnerlihuan%E5%8D%9A%E5%AE%A2/Android%E5%A4%9A%E5%AA%92%E4%BD%93%E5%BC%80%E5%8F%91%28%E4%B9%9D%29----Video%20Buffer%E4%BC%A0%E8%BE%93%E4%B8%8EAudio%20Playback%E6%B5%81%E7%A8%8B/meizi.jpg&quot; alt=&quot;妹子&quot;&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;上一篇我们简要分析了一下播放流程，主要讲了音频、视频播放和音视频同步的问题。但是对于视频读取buffer还有音频start之后发生的流程都没有分析。本节我们就这两点再分析一番。&lt;br&gt;
    
    </summary>
    
      <category term="Android技术点" scheme="http://windrunnerlihuan.com/categories/Android%E6%8A%80%E6%9C%AF%E7%82%B9/"/>
    
    
      <category term="多媒体" scheme="http://windrunnerlihuan.com/tags/%E5%A4%9A%E5%AA%92%E4%BD%93/"/>
    
  </entry>
  
</feed>
