-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
25 lines (25 loc) · 263 KB
/
index.html
File metadata and controls
25 lines (25 loc) · 263 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=2"><meta name="theme-color" content="#222"><meta name="generator" content="Hexo 5.4.0"><link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png"><link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png"><link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png"><link rel="mask-icon" href="/images/logo.svg" color="#222"><link rel="stylesheet" href="/css/main.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.3/css/all.min.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/animate.css@3.1.1/animate.min.css"><script class="hexo-configurations">var NexT=window.NexT||{},CONFIG={hostname:"www.vectoros.club",root:"/",images:"/images",scheme:"Muse",version:"8.3.0",exturl:!1,sidebar:{position:"left",display:"always",padding:18,offset:12},copycode:!1,bookmark:{enable:!1,color:"#222",save:"auto"},fancybox:!1,mediumzoom:!1,lazyload:!1,pangu:!1,comments:{style:"tabs",active:"gitalk",storage:!0,lazyload:!1,nav:null,activeClass:"gitalk"},motion:{enable:!0,async:!1,transition:{post_block:"fadeIn",post_header:"fadeInDown",post_body:"fadeInDown",coll_header:"fadeInLeft",sidebar:"fadeInUp"}},prism:!1,i18n:{placeholder:"搜索...",empty:"没有找到任何搜索结果:${query}",hits_time:"找到 ${hits} 个搜索结果(用时 ${time} 毫秒)",hits:"找到 ${hits} 个搜索结果"},path:"/search.xml",localsearch:{enable:!0,trigger:"auto",top_n_per_article:1,unescape:!1,preload:!1}}</script><meta property="og:type" content="website"><meta property="og:title" content="Keep Learning"><meta property="og:url" content="http://www.vectoros.club/index.html"><meta property="og:site_name" content="Keep Learning"><meta property="og:locale" content="zh_CN"><meta property="article:author" content="Vectoros"><meta property="article:tag" content="Android, Deep Learning, Tensorflow"><meta name="twitter:card" content="summary"><link rel="canonical" href="http://www.vectoros.club/"><script class="page-configurations">CONFIG.page={sidebar:"",isHome:!0,isPost:!1,lang:"zh-CN"}</script><title>Keep Learning</title><noscript><style>body{margin-top:2rem}.use-motion .collection-header,.use-motion .comments,.use-motion .menu-item,.use-motion .pagination,.use-motion .post-block,.use-motion .post-body,.use-motion .post-header,.use-motion .sidebar{visibility:visible}.use-motion .footer,.use-motion .header,.use-motion .site-brand-container .toggle{opacity:initial}.use-motion .custom-logo-image,.use-motion .site-subtitle,.use-motion .site-title{opacity:initial;top:initial}.use-motion .logo-line{transform:scaleX(1)}.search-pop-overlay,.sidebar-nav{display:none}.sidebar-panel{display:block}</style></noscript></head><body itemscope itemtype="http://schema.org/WebPage" class="use-motion"><div class="headband"></div><main class="main"><header class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="header-inner"><div class="site-brand-container"><div class="site-nav-toggle"><div class="toggle" aria-label="切换导航栏" role="button"><span class="toggle-line"></span> <span class="toggle-line"></span> <span class="toggle-line"></span></div></div><div class="site-meta"><a href="/" class="brand" rel="start"><i class="logo-line"></i><h1 class="site-title">Keep Learning</h1><i class="logo-line"></i></a></div><div class="site-nav-right"><div class="toggle popup-trigger"><i class="fa fa-search fa-fw fa-lg"></i></div></div></div><nav class="site-nav"><ul class="main-menu menu"><li class="menu-item menu-item-home"><a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a></li><li class="menu-item menu-item-about"><a href="/about/" rel="section"><i class="fa fa-user fa-fw"></i>关于</a></li><li class="menu-item menu-item-tags"><a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a></li><li class="menu-item menu-item-categories"><a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a></li><li class="menu-item menu-item-archives"><a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a></li><li class="menu-item menu-item-search"><a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索</a></li></ul></nav><div class="search-pop-overlay"><div class="popup search-popup"><div class="search-header"><span class="search-icon"><i class="fa fa-search"></i></span><div class="search-input-container"><input autocomplete="off" autocapitalize="off" maxlength="80" placeholder="搜索..." spellcheck="false" type="search" class="search-input"></div><span class="popup-btn-close" role="button"><i class="fa fa-times-circle"></i></span></div><div class="search-result-container no-result"><div class="search-result-icon"><i class="fa fa-spinner fa-pulse fa-5x"></i></div></div></div></div></div><div class="toggle sidebar-toggle" role="button"><span class="toggle-line"></span> <span class="toggle-line"></span> <span class="toggle-line"></span></div><aside class="sidebar"><div class="sidebar-inner sidebar-overview-active"><ul class="sidebar-nav"><li class="sidebar-nav-toc">文章目录</li><li class="sidebar-nav-overview">站点概览</li></ul><div class="sidebar-panel-container"><div class="post-toc-wrap sidebar-panel"></div><div class="site-overview-wrap sidebar-panel"><div class="site-author site-overview-item animated" itemprop="author" itemscope itemtype="http://schema.org/Person"><img class="site-author-image" itemprop="image" alt="Vectoros" src="/uploads/avatar.webp"><p class="site-author-name" itemprop="name">Vectoros</p><div class="site-description" itemprop="description"></div></div><div class="site-state-wrap site-overview-item animated"><nav class="site-state"><div class="site-state-item site-state-posts"><a href="/archives/"><span class="site-state-item-count">17</span> <span class="site-state-item-name">日志</span></a></div><div class="site-state-item site-state-categories"><a href="/categories/"><span class="site-state-item-count">29</span> <span class="site-state-item-name">分类</span></a></div><div class="site-state-item site-state-tags"><a href="/tags/"><span class="site-state-item-count">27</span> <span class="site-state-item-name">标签</span></a></div></nav></div><div class="links-of-author site-overview-item animated"><span class="links-of-author-item"><a href="https://github.com/vectoros" title="GitHub → https://github.com/vectoros" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a> </span><span class="links-of-author-item"><a href="mailto:vectoros@outlook.com" title="E-Mail → mailto:vectoros@outlook.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a></span></div></div></div></div></aside><div class="sidebar-dimmer"></div></header><div class="back-to-top" role="button" aria-label="返回顶部"><i class="fa fa-arrow-up"></i> <span>0%</span></div><a href="https://github.com/vectoros" class="github-corner" title="Follow me on GitHub" aria-label="Follow me on GitHub" rel="noopener" target="_blank"><svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin:130px 106px" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><noscript><div class="noscript-warning">Theme NexT works best with JavaScript enabled</div></noscript><div class="main-inner index posts-expand"><div class="post-block"><article itemscope itemtype="http://schema.org/Article" class="post-content"><link itemprop="mainEntityOfPage" href="http://www.vectoros.club/post/1dbe5134.html"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="image" content="/uploads/avatar.webp"><meta itemprop="name" content="Vectoros"><meta itemprop="description" content=""></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="Keep Learning"></span><header class="post-header"><h2 class="post-title" itemprop="name headline"><a href="/post/1dbe5134.html" class="post-title-link" itemprop="url">Hexo tutorial</a></h2><div class="post-meta-container"><div class="post-meta"><span class="post-meta-item"><span class="post-meta-item-icon"><i class="far fa-calendar"></i> </span><span class="post-meta-item-text">发表于</span> <time title="创建时间:2023-04-15 22:49:21" itemprop="dateCreated datePublished" datetime="2023-04-15T22:49:21+08:00">2023-04-15</time> </span><span class="post-meta-item"><span class="post-meta-item-icon"><i class="far fa-folder"></i> </span><span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Web/" itemprop="url" rel="index"><span itemprop="name">Web</span></a></span></span></div></div></header><div class="post-body" itemprop="articleBody"><p>Welcome to <a target="_blank" rel="noopener" href="https://hexo.io/">Hexo</a>! This is your very first post. Check <a target="_blank" rel="noopener" href="https://hexo.io/docs/">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a target="_blank" rel="noopener" href="https://hexo.io/docs/troubleshooting.html">troubleshooting</a> or you can ask me on <a target="_blank" rel="noopener" href="https://github.com/hexojs/hexo/issues">GitHub</a>.</p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo new <span class="string">"My New Post"</span></span><br></pre></td></tr></table></figure><p>More info: <a target="_blank" rel="noopener" href="https://hexo.io/docs/writing.html">Writing</a></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo server</span><br></pre></td></tr></table></figure><p>OR</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo s</span><br></pre></td></tr></table></figure><p>More info: <a target="_blank" rel="noopener" href="https://hexo.io/docs/server.html">Server</a></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo generate</span><br></pre></td></tr></table></figure><p>OR</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo g</span><br></pre></td></tr></table></figure><p>More info: <a target="_blank" rel="noopener" href="https://hexo.io/docs/generating.html">Generating</a></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo deploy</span><br></pre></td></tr></table></figure><p>OR</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo d</span><br></pre></td></tr></table></figure><h3 id="Generate-Categories"><a href="#Generate-Categories" class="headerlink" title="Generate Categories"></a>Generate Categories</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo new page categories</span><br></pre></td></tr></table></figure><p>Then open <code>source/categories/index.md</code>, Add <code>type: "categories"</code></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line">title: categories</span><br><span class="line">date: 2019-03-09 13:31:42</span><br><span class="line">type: "categories"</span><br><span class="line">comments: false</span><br><span class="line">---</span><br></pre></td></tr></table></figure><h3 id="Generate-Tags"><a href="#Generate-Tags" class="headerlink" title="Generate Tags"></a>Generate Tags</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo new page tags</span><br></pre></td></tr></table></figure><p>Then open <code>source/tags/index.md</code>, Add <code>type: "tags"</code></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line">title: categories</span><br><span class="line">date: 2019-03-09 13:31:42</span><br><span class="line">type: "tags"</span><br><span class="line">comments: false</span><br><span class="line">---</span><br></pre></td></tr></table></figure><h3 id="Using-tags-or-categories"><a href="#Using-tags-or-categories" class="headerlink" title="Using tags or categories"></a>Using tags or categories</h3><p>Adding categories or tags description on page title</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line">title: Hexo tutorial</span><br><span class="line">tag: [Hexo,Tutorial]</span><br><span class="line">categories: </span><br><span class="line">- Web</span><br><span class="line">---</span><br></pre></td></tr></table></figure><h3 id="Clean-caches-and-regenerated"><a href="#Clean-caches-and-regenerated" class="headerlink" title="Clean caches and regenerated"></a>Clean caches and regenerated</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ hexo clean</span><br><span class="line">$ hexo g</span><br></pre></td></tr></table></figure><p>More info: <a target="_blank" rel="noopener" href="https://hexo.io/docs/deployment.html">Deployment</a></p></div><footer class="post-footer"><div class="post-eof"></div></footer></article></div><div class="post-block"><article itemscope itemtype="http://schema.org/Article" class="post-content"><link itemprop="mainEntityOfPage" href="http://www.vectoros.club/post/69b727d7.html"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="image" content="/uploads/avatar.webp"><meta itemprop="name" content="Vectoros"><meta itemprop="description" content=""></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="Keep Learning"></span><header class="post-header"><h2 class="post-title" itemprop="name headline"><a href="/post/69b727d7.html" class="post-title-link" itemprop="url">Android Camera 格式</a></h2><div class="post-meta-container"><div class="post-meta"><span class="post-meta-item"><span class="post-meta-item-icon"><i class="far fa-calendar"></i> </span><span class="post-meta-item-text">发表于</span> <time title="创建时间:2022-04-04 17:34:14" itemprop="dateCreated datePublished" datetime="2022-04-04T17:34:14+08:00">2022-04-04</time> </span><span class="post-meta-item"><span class="post-meta-item-icon"><i class="far fa-folder"></i> </span><span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/" itemprop="url" rel="index"><span itemprop="name">Android</span></a> </span>, <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/Framework/" itemprop="url" rel="index"><span itemprop="name">Framework</span></a> </span>, <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/Framework/Camera/" itemprop="url" rel="index"><span itemprop="name">Camera</span></a></span></span></div></div></header><div class="post-body" itemprop="articleBody"><p>Andriod Camera 推荐使用YUV格式,在Camera API1 中,推荐使用 NV21 和 YV12,因为这两种格式支持所有的Camera设备。<br>在Camera API2 中,推荐试用 YUV_420_888</p><h1 id="YUV简介"><a href="#YUV简介" class="headerlink" title="YUV简介"></a>YUV简介</h1><p>不同于RGB颜色模型,使用R,G,B三个颜色分量来表示颜色。YUV使用明亮度”Y”, 色度”U,V”来表示颜色。<br>其中明亮度”Y”(Luninance或Luma)就是我们常见的灰度值, 色度(Chrominance或Chroma)用于指定像素的颜色。<br>其中:U(Cb), 代表蓝色; V(Cr), 代表红色。所有YUV还有一种说法就是YCbCr</p><p>YUV的优点:</p><ol><li>优化彩色视频信号传输,可以很方便的兼容老式黑白电视。黑白电视只需要处理Y分量,彩色在其基础上加上U(Cb), V(Cr)两个分量即可。</li><li>降低传输的数据量,以常见的YUV420来看,每4个Y共用一组UV分量给,一个YUV占用 8+2+2 = 12bits = 1.5Byte;而RGB需要8+8+8 = 24bits = 3Byte;节省了一半的数据。</li></ol><h1 id="常用的格式"><a href="#常用的格式" class="headerlink" title="常用的格式"></a>常用的格式</h1><ul><li><p>YUV420SP</p><ul><li><p>NV21</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">YYYYYYYY VUVU</span><br></pre></td></tr></table></figure></li><li><p>NV12</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">YYYYYYYY UVUV</span><br></pre></td></tr></table></figure></li></ul></li></ul><ul><li><p>YUV420P 平面模式, Y,U,V分别在不同的平面,是标准的4:2:0</p><ul><li><p>YV12</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">YYYYYYYY VVUU</span><br></pre></td></tr></table></figure></li><li><p>I420(YU12)</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">YYYYYYYY UUVV</span><br></pre></td></tr></table></figure></li></ul></li></ul><h1 id="内存布局"><a href="#内存布局" class="headerlink" title="内存布局"></a>内存布局</h1><p>在实际使用中,一个YUV420图像大小,往往会比按照图像宽高计算的来的大。主要的原因就是一个数据对齐。这里有下面几个概念:</p><ul><li>width 图像宽度</li><li>rowStride 跨度,图像实际存储的宽度</li><li>height 图像高度</li><li>scanLines 扫描线。图像实际存储高度</li></ul><p>在Android手机的Camera框架中,HAL层的Buffer,都是通过<code>GraphicBufferMapper</code>去分配处理的。我们调用<code>GraphicBufferMapper</code>的lock接口去获取<code>GraphicBuffer</code>时,传入的参数是图像的宽高,返回的实际内存大小是经过对齐后的。</p><h2 id="高通-NV12"><a href="#高通-NV12" class="headerlink" title="高通 NV12"></a>高通 NV12</h2><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* Venus NV12:</span></span><br><span class="line"><span class="comment"> * YUV 4:2:0 image with a plane of 8 bit Y samples followed</span></span><br><span class="line"><span class="comment"> * by an interleaved U/V plane containing 8 bit 2x2 subsampled</span></span><br><span class="line"><span class="comment"> * colour difference samples.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <-------- Y/UV_Stride --------></span></span><br><span class="line"><span class="comment"> * <------- Width -------></span></span><br><span class="line"><span class="comment"> * Y Y Y Y Y Y Y Y Y Y Y Y . . . . ^ ^</span></span><br><span class="line"><span class="comment"> * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | |</span></span><br><span class="line"><span class="comment"> * Y Y Y Y Y Y Y Y Y Y Y Y . . . . Height |</span></span><br><span class="line"><span class="comment"> * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | Y_Scanlines</span></span><br><span class="line"><span class="comment"> * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | |</span></span><br><span class="line"><span class="comment"> * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | |</span></span><br><span class="line"><span class="comment"> * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | |</span></span><br><span class="line"><span class="comment"> * Y Y Y Y Y Y Y Y Y Y Y Y . . . . V |</span></span><br><span class="line"><span class="comment"> * . . . . . . . . . . . . . . . . |</span></span><br><span class="line"><span class="comment"> * . . . . . . . . . . . . . . . . |</span></span><br><span class="line"><span class="comment"> * . . . . . . . . . . . . . . . . |</span></span><br><span class="line"><span class="comment"> * . . . . . . . . . . . . . . . . V</span></span><br><span class="line"><span class="comment"> * U V U V U V U V U V U V . . . . ^</span></span><br><span class="line"><span class="comment"> * U V U V U V U V U V U V . . . . |</span></span><br><span class="line"><span class="comment"> * U V U V U V U V U V U V . . . . |</span></span><br><span class="line"><span class="comment"> * U V U V U V U V U V U V . . . . UV_Scanlines</span></span><br><span class="line"><span class="comment"> * . . . . . . . . . . . . . . . . |</span></span><br><span class="line"><span class="comment"> * . . . . . . . . . . . . . . . . V</span></span><br><span class="line"><span class="comment"> * . . . . . . . . . . . . . . . . --> Buffer size alignment</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * Y_Stride : Width aligned to 128</span></span><br><span class="line"><span class="comment"> * UV_Stride : Width aligned to 128</span></span><br><span class="line"><span class="comment"> * Y_Scanlines: Height aligned to 32</span></span><br><span class="line"><span class="comment"> * UV_Scanlines: Height/2 aligned to 16</span></span><br><span class="line"><span class="comment"> * Extradata: Arbitrary (software-imposed) padding</span></span><br><span class="line"><span class="comment"> * Total size = align((Y_Stride * Y_Scanlines</span></span><br><span class="line"><span class="comment"> * + UV_Stride * UV_Scanlines</span></span><br><span class="line"><span class="comment"> * + max(Extradata, Y_Stride * 8), 4096)</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="高通NV21"><a href="#高通NV21" class="headerlink" title="高通NV21"></a>高通NV21</h2><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* Venus NV21:</span></span><br><span class="line"><span class="comment"> * YUV 4:2:0 image with a plane of 8 bit Y samples followed</span></span><br><span class="line"><span class="comment"> * by an interleaved V/U plane containing 8 bit 2x2 subsampled</span></span><br><span class="line"><span class="comment"> * colour difference samples.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <-------- Y/UV_Stride --------></span></span><br><span class="line"><span class="comment"> * <------- Width -------></span></span><br><span class="line"><span class="comment"> * Y Y Y Y Y Y Y Y Y Y Y Y . . . . ^ ^</span></span><br><span class="line"><span class="comment"> * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | |</span></span><br><span class="line"><span class="comment"> * Y Y Y Y Y Y Y Y Y Y Y Y . . . . Height |</span></span><br><span class="line"><span class="comment"> * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | Y_Scanlines</span></span><br><span class="line"><span class="comment"> * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | |</span></span><br><span class="line"><span class="comment"> * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | |</span></span><br><span class="line"><span class="comment"> * Y Y Y Y Y Y Y Y Y Y Y Y . . . . | |</span></span><br><span class="line"><span class="comment"> * Y Y Y Y Y Y Y Y Y Y Y Y . . . . V |</span></span><br><span class="line"><span class="comment"> * . . . . . . . . . . . . . . . . |</span></span><br><span class="line"><span class="comment"> * . . . . . . . . . . . . . . . . |</span></span><br><span class="line"><span class="comment"> * . . . . . . . . . . . . . . . . |</span></span><br><span class="line"><span class="comment"> * . . . . . . . . . . . . . . . . V</span></span><br><span class="line"><span class="comment"> * V U V U V U V U V U V U . . . . ^</span></span><br><span class="line"><span class="comment"> * V U V U V U V U V U V U . . . . |</span></span><br><span class="line"><span class="comment"> * V U V U V U V U V U V U . . . . |</span></span><br><span class="line"><span class="comment"> * V U V U V U V U V U V U . . . . UV_Scanlines</span></span><br><span class="line"><span class="comment"> * . . . . . . . . . . . . . . . . |</span></span><br><span class="line"><span class="comment"> * . . . . . . . . . . . . . . . . V</span></span><br><span class="line"><span class="comment"> * . . . . . . . . . . . . . . . . --> Padding & Buffer size alignment</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * Y_Stride : Width aligned to 128</span></span><br><span class="line"><span class="comment"> * UV_Stride : Width aligned to 128</span></span><br><span class="line"><span class="comment"> * Y_Scanlines: Height aligned to 32</span></span><br><span class="line"><span class="comment"> * UV_Scanlines: Height/2 aligned to 16</span></span><br><span class="line"><span class="comment"> * Extradata: Arbitrary (software-imposed) padding</span></span><br><span class="line"><span class="comment"> * Total size = align((Y_Stride * Y_Scanlines</span></span><br><span class="line"><span class="comment"> * + UV_Stride * UV_Scanlines</span></span><br><span class="line"><span class="comment"> * + max(Extradata, Y_Stride * 8), 4096)</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure></div><footer class="post-footer"><div class="post-eof"></div></footer></article></div><div class="post-block"><article itemscope itemtype="http://schema.org/Article" class="post-content"><link itemprop="mainEntityOfPage" href="http://www.vectoros.club/post/31ae23dc.html"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="image" content="/uploads/avatar.webp"><meta itemprop="name" content="Vectoros"><meta itemprop="description" content=""></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="Keep Learning"></span><header class="post-header"><h2 class="post-title" itemprop="name headline"><a href="/post/31ae23dc.html" class="post-title-link" itemprop="url">Android Camera 深度解析</a></h2><div class="post-meta-container"><div class="post-meta"><span class="post-meta-item"><span class="post-meta-item-icon"><i class="far fa-calendar"></i> </span><span class="post-meta-item-text">发表于</span> <time title="创建时间:2022-01-02 22:14:59" itemprop="dateCreated datePublished" datetime="2022-01-02T22:14:59+08:00">2022-01-02</time> </span><span class="post-meta-item"><span class="post-meta-item-icon"><i class="far fa-folder"></i> </span><span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/" itemprop="url" rel="index"><span itemprop="name">Android</span></a> </span>, <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/Framework/" itemprop="url" rel="index"><span itemprop="name">Framework</span></a> </span>, <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/Framework/Camera/" itemprop="url" rel="index"><span itemprop="name">Camera</span></a></span></span></div></div></header><div class="post-body" itemprop="articleBody"><p>这是一个系列的文章,主要从HAL层,Framework层,应用层三个方面来刨析Android Camera框架的实现原理和设计理念。源码以AOSP android 11版本为例。主要参考Android官网的文档。</p><p>这里我会从上到下依次按层级的方式,以Camera2 API和HAL3来解读Android Camera 的源码,中间回掺杂一些额外的补充知识点。</p><p>首先看下SDK中的相关内容</p><h2 id="相关的类"><a href="#相关的类" class="headerlink" title="相关的类"></a>相关的类</h2><p>在Camera API2 中,主要用到以下几个Package/类</p><ul><li>Package: android.hardware.camera2</li><li>Camera: API1的接口</li><li>SurfaceView: 处理预览,渲染的呈现</li><li>MediaRecorder: 用于录像</li><li>Intent: 提供<code>MediaStore.ACTION_IMAGE_CAPTURE</code> 或者 <code>MediaStore.ACTION_VIDEO_CAPTURE</code> 的Intent操作类型用于捕获图像或者视频,不需要直接使用Camera对象</li></ul><h2 id="清单声明"><a href="#清单声明" class="headerlink" title="清单声明"></a>清单声明</h2><h3 id="权限申请"><a href="#权限申请" class="headerlink" title="权限申请"></a>权限申请</h3><ul><li><p>相机权限</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">"android.permission.CAMERA"</span> /></span></span><br></pre></td></tr></table></figure><p>使用现有相机来打开相机(Intent),不需要申请权限</p></li><li><p>存储权限</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">"android.permission.WRITE_EXTERNAL_STORAGE"</span> /></span></span><br></pre></td></tr></table></figure></li><li><p>录音权限</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">"android.permission.RECORD_AUDIO"</span> /></span></span><br></pre></td></tr></table></figure></li><li><p>位置权限</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">"android.permission.ACCESS_FINE_LOCATION"</span> /></span></span><br><span class="line">...</span><br><span class="line"><span class="comment"><!-- Needed only if your app targets Android 5.0 (API level 21) or higher. --></span></span><br><span class="line"><span class="tag"><<span class="name">uses-feature</span> <span class="attr">android:name</span>=<span class="string">"android.hardware.location.gps"</span> /></span></span><br></pre></td></tr></table></figure></li></ul><h3 id="功能声明"><a href="#功能声明" class="headerlink" title="功能声明"></a>功能声明</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">uses-feature</span> <span class="attr">android:name</span>=<span class="string">"android.hardware.camera"</span> /></span></span><br></pre></td></tr></table></figure><p>非必需情况</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><uses-feature android:name="android.hardware.camera" android:required="false" /></span><br></pre></td></tr></table></figure><h2 id="开发相机应用"><a href="#开发相机应用" class="headerlink" title="开发相机应用"></a>开发相机应用</h2><p>在官方开发文档中,建议开发者使用Camera X来开发相机应用。</p><p>参考:<br><a target="_blank" rel="noopener" href="https://developer.android.com/guide/topics/media/camera">https://developer.android.com/guide/topics/media/camera</a></p><p><a target="_blank" rel="noopener" href="https://developer.android.com/training/camera2">https://developer.android.com/training/camera2</a></p></div><footer class="post-footer"><div class="post-eof"></div></footer></article></div><div class="post-block"><article itemscope itemtype="http://schema.org/Article" class="post-content"><link itemprop="mainEntityOfPage" href="http://www.vectoros.club/post/fe9083b4.html"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="image" content="/uploads/avatar.webp"><meta itemprop="name" content="Vectoros"><meta itemprop="description" content=""></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="Keep Learning"></span><header class="post-header"><h2 class="post-title" itemprop="name headline"><a href="/post/fe9083b4.html" class="post-title-link" itemprop="url">WSL2中编译安卓源码</a></h2><div class="post-meta-container"><div class="post-meta"><span class="post-meta-item"><span class="post-meta-item-icon"><i class="far fa-calendar"></i> </span><span class="post-meta-item-text">发表于</span> <time title="创建时间:2020-02-07 13:04:36" itemprop="dateCreated datePublished" datetime="2020-02-07T13:04:36+08:00">2020-02-07</time> </span><span class="post-meta-item"><span class="post-meta-item-icon"><i class="far fa-folder"></i> </span><span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/" itemprop="url" rel="index"><span itemprop="name">Android</span></a> </span>, <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/WSL2/" itemprop="url" rel="index"><span itemprop="name">WSL2</span></a> </span>, <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/WSL2/AOSP/" itemprop="url" rel="index"><span itemprop="name">AOSP</span></a> </span>, <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/WSL2/AOSP/Android-Pie/" itemprop="url" rel="index"><span itemprop="name">Android Pie</span></a></span></span></div></div></header><div class="post-body" itemprop="articleBody"><p>最新得Windows 10 版本18917或更高版本中,可以安装WSL2子系统,相比于WSL1,WSL2相当于提供了更加完整的Linux支持,因此可以用来编译Android系统源码,也不用再单独安装虚拟机了。</p><h1 id="系统要求"><a href="#系统要求" class="headerlink" title="系统要求"></a>系统要求</h1><ul><li>Windows 10 版本18917或更高版本中</li><li>足够的存储空间</li></ul><h1 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h1><h2 id="启用安装WSL2"><a href="#启用安装WSL2" class="headerlink" title="启用安装WSL2"></a>启用安装WSL2</h2><p>参考微软官方:<a target="_blank" rel="noopener" href="https://docs.microsoft.com/zh-cn/windows/wsl/wsl2-install">https://docs.microsoft.com/zh-cn/windows/wsl/wsl2-install</a></p><h2 id="安装Ubuntu"><a href="#安装Ubuntu" class="headerlink" title="安装Ubuntu"></a>安装Ubuntu</h2><p>应用商店中搜索Ubuntu,安装Ubuntu 18.04发行版</p><h2 id="修改安装源"><a href="#修改安装源" class="headerlink" title="修改安装源"></a>修改安装源</h2><p>默认的源更新起来慢,可以修改成阿里云的源</p><ul><li><p>备份原始源</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo cp /etc/apt/sources.list /etc/apt/sourses.list.bak</span><br></pre></td></tr></table></figure></li><li><p>更新阿里源</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">sudo vim /etc/apt/sources.list</span><br><span class="line"><span class="comment"># 将里面的内容替换成</span></span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse</span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse</span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse</span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse</span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse</span><br></pre></td></tr></table></figure></li><li><p>更新</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo apt update</span><br><span class="line">sudo apt upgrade</span><br></pre></td></tr></table></figure></li></ul><h2 id="Windows-Terminal"><a href="#Windows-Terminal" class="headerlink" title="Windows Terminal"></a>Windows Terminal</h2><p>Windows Terminal是微软推出的一个现代化Terminal工具,很好用</p><ul><li>到应用商店搜索Windows Terminal安装</li></ul><h2 id="Git-amp-Vim"><a href="#Git-amp-Vim" class="headerlink" title="Git & Vim"></a>Git & Vim</h2><ul><li>安装<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install git vim</span><br></pre></td></tr></table></figure></li><li>配置<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git config --global user.name "your name"</span><br><span class="line">git config --global user.email "your email"</span><br></pre></td></tr></table></figure><h2 id="repo"><a href="#repo" class="headerlink" title="repo"></a>repo</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">mkdir ~/bin</span><br><span class="line">PATH=~/bin:$PATH</span><br><span class="line">curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo</span><br><span class="line">## 如果上述 URL 不可访问,可以用下面的:</span><br><span class="line">## curl -sSL 'https://gerrit-googlesource.proxy.ustclug.org/git-repo/+/master/repo?format=TEXT' |base64 -d > ~/bin/repo</span><br><span class="line">chmod a+x ~/bin/repo</span><br></pre></td></tr></table></figure></li></ul><h2 id="JDK"><a href="#JDK" class="headerlink" title="JDK"></a>JDK</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install openjdk-8-jdk</span><br></pre></td></tr></table></figure><h2 id="设置CCCache"><a href="#设置CCCache" class="headerlink" title="设置CCCache"></a>设置CCCache</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">vim ~/.bashrc</span><br><span class="line"># 追加以下内容</span><br><span class="line">export USE_CCACHE=1</span><br><span class="line">export CCACHE_DIR=/mnt/e/workspace/CCACHE/.ccache</span><br></pre></td></tr></table></figure><h1 id="针对源码工作目录,开启大小写敏感(重要)"><a href="#针对源码工作目录,开启大小写敏感(重要)" class="headerlink" title="针对源码工作目录,开启大小写敏感(重要)"></a>针对源码工作目录,开启大小写敏感(重要)</h1><ul><li>Windows系统中文件和文件夹默认是不区分大小写的,但是编译Android源码,需要区分大小的系统。</li><li>为了给WSL提供更好的支持,微软从Windows10 18917更新开始,为NTFS文件系统新增了一个<code>SetCaseSensitiveInfo</code>标志。可以有选择的根据所需的文件夹启用此flag,启用之后,NTFS文件系统就会针对<strong>该文件夹及其子文件</strong>视为区分大小写。</li><li>此功能不仅可以在WSL中起作用,也可以在Windows下起作用。</li></ul><h2 id="开启方式"><a href="#开启方式" class="headerlink" title="开启方式"></a>开启方式</h2><ul><li>以管理员身份打开命令提示符或者Powershell</li><li>执行以下命令开启<figure class="highlight bat"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">fsutil file SetCaseSensitiveInfo E:\workspace\AOSP enable</span><br><span class="line">fsutil file SetCaseSensitiveInfo E:\workspace\CCACHE enable</span><br></pre></td></tr></table></figure></li><li>执行以下命令关闭<figure class="highlight bat"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">fsutil file SetCaseSensitiveInfo E:\workspace\AOSP disable</span><br><span class="line">fsutil file SetCaseSensitiveInfo E:\workspace\CCACHE disable</span><br></pre></td></tr></table></figure><h1 id="下载代码"><a href="#下载代码" class="headerlink" title="下载代码"></a>下载代码</h1><h2 id="初始化仓库"><a href="#初始化仓库" class="headerlink" title="初始化仓库"></a>初始化仓库</h2>这里使用中科大的镜像:<a target="_blank" rel="noopener" href="https://lug.ustc.edu.cn/wiki/mirrors/help/aosp">https://lug.ustc.edu.cn/wiki/mirrors/help/aosp</a></li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /mnt/e/workspace/AOSP</span><br><span class="line">repo init -u git://mirrors.ustc.edu.cn/aosp/platform/manifest</span><br><span class="line"><span class="comment">## 如果提示无法连接到 gerrit.googlesource.com,可以编辑 ~/bin/repo,把 REPO_URL 一行替换成下面的:</span></span><br><span class="line"><span class="comment">## REPO_URL = 'https://gerrit-googlesource.proxy.ustclug.org/git-repo'</span></span><br></pre></td></tr></table></figure><h2 id="初始化特定版本"><a href="#初始化特定版本" class="headerlink" title="初始化特定版本"></a>初始化特定版本</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">repo init -u git://mirrors.ustc.edu.cn/aosp/platform/manifest -b android-9.0.0_r40</span><br></pre></td></tr></table></figure><h2 id="同步源码"><a href="#同步源码" class="headerlink" title="同步源码"></a>同步源码</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">repo sync</span><br></pre></td></tr></table></figure><h2 id="也可以参考Google官方教程"><a href="#也可以参考Google官方教程" class="headerlink" title="也可以参考Google官方教程"></a>也可以参考Google官方教程</h2><ul><li><a target="_blank" rel="noopener" href="https://source.android.com/source/downloading.html">https://source.android.com/source/downloading.html</a></li></ul><h1 id="编译"><a href="#编译" class="headerlink" title="编译"></a>编译</h1><p>我这里选择编译Pixel版本,因为手里有一个Pixel手机</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">source</span> build/envsetup.sh</span><br><span class="line">lunch 45 <span class="comment"># aosp_sailfish-userdebug</span></span><br><span class="line">make </span><br></pre></td></tr></table></figure><h1 id="编译错误处理"><a href="#编译错误处理" class="headerlink" title="编译错误处理"></a>编译错误处理</h1><ul><li><p><code>dex2oatd F dex2oat did not finish after 2850 seconds</code></p><p>修改<code>build/core/</code>目录下的两个文件</p><figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">diff --git a/core/dex_preopt_libart.mk b/core/ dex_preopt_libart.mk</span></span><br><span class="line"><span class="comment">index 9c4d55de7..3b1158d9c 100644</span></span><br><span class="line"><span class="comment">--- a/core/dex_preopt_libart.mk</span></span><br><span class="line"><span class="comment">+++ b/core/dex_preopt_libart.mk</span></span><br><span class="line"><span class="meta">@@ -184,7 +184,7 @@</span> source build/make/core/ verify_uses_libraries.sh "$(1)" && \</span><br><span class="line"> source build/make/core/construct_context.sh "$ (PRIVATE_CONDITIONAL_USES_LIBRARIES_HOST)" "$ (PRIVATE_CONDITIONAL_USES_LIBRARIES_TARGET)" && \</span><br><span class="line"> ,) \</span><br><span class="line"> ANDROID_LOG_TAGS="*:e" $(DEX2OAT) \</span><br><span class="line"><span class="deletion">- --runtime-arg -Xms$(DEX2OAT_XMS) --runtime-arg -Xmx$(DEX2OAT_XMX) \</span></span><br><span class="line"><span class="addition">+ --runtime-arg -Xms$(DEX2OAT_XMS) -j1 --runtime-arg -Xmx$(DEX2OAT_XMX) \</span></span><br><span class="line"> $${class_loader_context_arg} \</span><br><span class="line"> $${stored_class_loader_context_arg} \</span><br><span class="line"> --boot-image=$ (PRIVATE_DEX_PREOPT_IMAGE_LOCATION) \</span><br><span class="line"><span class="comment">diff --git a/core/dex_preopt_libart_boot.mk b/core/ dex_preopt_libart_boot.mk</span></span><br><span class="line"><span class="comment">index a5e7e881a..fadd6d794 100644</span></span><br><span class="line"><span class="comment">--- a/core/dex_preopt_libart_boot.mk</span></span><br><span class="line"><span class="comment">+++ b/core/dex_preopt_libart_boot.mk</span></span><br><span class="line"><span class="meta">@@ -102,7 +102,7 @@</span> $($(my_2nd_arch_prefix) DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME) : $(LIBART_TARGE</span><br><span class="line"> @rm -f $(dir $($(PRIVATE_2ND_ARCH_VAR_PREFIX) LIBART_TARGET_BOOT_OAT_UNSTRIPPED))/*.art</span><br><span class="line"> @rm -f $(dir $($(PRIVATE_2ND_ARCH_VAR_PREFIX) LIBART_TARGET_BOOT_OAT_UNSTRIPPED))/*.oat</span><br><span class="line"> @rm -f $(dir $($(PRIVATE_2ND_ARCH_VAR_PREFIX) LIBART_TARGET_BOOT_OAT_UNSTRIPPED))/*.art.rel</span><br><span class="line"><span class="deletion">- $(hide) $(DEX2OAT_BOOT_IMAGE_LOG_TAGS) $ (DEX2OAT) --runtime-arg -Xms$(DEX2OAT_IMAGE_XMS) \</span></span><br><span class="line"><span class="addition">+ $(hide) $(DEX2OAT_BOOT_IMAGE_LOG_TAGS) $ (DEX2OAT) -j1 --runtime-arg -Xms$(DEX2OAT_IMAGE_XMS) \</span></span><br><span class="line"> --runtime-arg -Xmx$(DEX2OAT_IMAGE_XMX) \</span><br><span class="line"> $(PRIVATE_BOOT_IMAGE_FLAGS) \</span><br><span class="line"> $(addprefix --dex-file=,$ (LIBART_TARGET_BOOT_DEX_FILES)) \</span><br></pre></td></tr></table></figure></li></ul></div><footer class="post-footer"><div class="post-eof"></div></footer></article></div><div class="post-block"><article itemscope itemtype="http://schema.org/Article" class="post-content"><link itemprop="mainEntityOfPage" href="http://www.vectoros.club/post/17976623.html"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="image" content="/uploads/avatar.webp"><meta itemprop="name" content="Vectoros"><meta itemprop="description" content=""></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="Keep Learning"></span><header class="post-header"><h2 class="post-title" itemprop="name headline"><a href="/post/17976623.html" class="post-title-link" itemprop="url">NDK JNI中动态注册和静态注册,native和static native区别</a></h2><div class="post-meta-container"><div class="post-meta"><span class="post-meta-item"><span class="post-meta-item-icon"><i class="far fa-calendar"></i> </span><span class="post-meta-item-text">发表于</span> <time title="创建时间:2019-10-17 20:11:59" itemprop="dateCreated datePublished" datetime="2019-10-17T20:11:59+08:00">2019-10-17</time> </span><span class="post-meta-item"><span class="post-meta-item-icon"><i class="far fa-folder"></i> </span><span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/" itemprop="url" rel="index"><span itemprop="name">Android</span></a> </span>, <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/NDK/" itemprop="url" rel="index"><span itemprop="name">NDK</span></a> </span>, <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/NDK/JNI/" itemprop="url" rel="index"><span itemprop="name">JNI</span></a></span></span></div></div></header><div class="post-body" itemprop="articleBody"><p>动态注册和静态注册在JNI开发中是必然会遇到的问题。在最新的AndroidStudio中,默认使用的是静态注册,但是动态注册确实一种更加灵活的方式。</p><h2 id="静态注册"><a href="#静态注册" class="headerlink" title="静态注册"></a>静态注册</h2><p>在AndroidStudio中,创建项目时选择Native C++项目,会帮我们默认创建以下几个文件。</p><ul><li><p>MainActivity.java Java文件,包含JNI Java层接口</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MainActivity</span> <span class="keyword">extends</span> <span class="title">AppCompatActivity</span> </span>{</span><br><span class="line"></span><br><span class="line"><span class="comment">// Used to load the 'native-lib' library on application startup.</span></span><br><span class="line"><span class="keyword">static</span> {</span><br><span class="line"> System.loadLibrary(<span class="string">"native-lib"</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span> </span>{</span><br><span class="line"> <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line"> setContentView(R.layout.activity_main);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// Example of a call to a native method</span></span><br><span class="line"> TextView tv = findViewById(R.id.sample_text);</span><br><span class="line"> tv.setText(stringFromJNI());</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * A native method that is implemented by the 'native-lib' native library,</span></span><br><span class="line"><span class="comment"> * which is packaged with this application.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">native</span> String <span class="title">stringFromJNI</span><span class="params">()</span></span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p>native-lib.cpp C++文件,包含JNI函数的实现</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><jni.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><string></span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">extern</span> <span class="string">"C"</span> JNIEXPORT jstring JNICALL</span><br><span class="line"><span class="built_in">Java_com_vectoros_jnimethod_MainActivity_stringFromJNI</span>(</span><br><span class="line"> JNIEnv *env,</span><br><span class="line"> jobject <span class="comment">/* this */</span>) {</span><br><span class="line"> std::string hello = <span class="string">"Hello from C++"</span>;</span><br><span class="line"> <span class="keyword">return</span> env-><span class="built_in">NewStringUTF</span>(hello.<span class="built_in">c_str</span>());</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p>CMakeLists.txt CMake编译脚本</p><figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">cmake_minimum_required(VERSION 3.4.1)</span><br><span class="line"></span><br><span class="line">add_library( <span class="comment"># Sets the name of the library.</span></span><br><span class="line"> native-lib</span><br><span class="line"> SHARED</span><br><span class="line"> native-lib.cpp)</span><br><span class="line"></span><br><span class="line">find_library( <span class="comment"># Sets the name of the path variable.</span></span><br><span class="line"> log-lib</span><br><span class="line"> log)</span><br><span class="line"></span><br><span class="line">target_link_libraries( <span class="comment"># Specifies the target library.</span></span><br><span class="line"> native-lib</span><br><span class="line"> ${log-lib})</span><br></pre></td></tr></table></figure></li></ul><h2 id="动态注册"><a href="#动态注册" class="headerlink" title="动态注册"></a>动态注册</h2><p>动态注册需要写的代码会多一些,我们可以参考Framework的很多JNI接口的实现。Java层的代码不需要变化,CMake也不需要修改(如果有引入其他头文件,需要在CMake里面增加对应的库)</p><ul><li><p>JNINativeMethod<br>动态注册过程中,需要使用结构体JNINativeMethod来记录java方法和jni函数的对应关系</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> {</span></span><br><span class="line"> <span class="keyword">const</span> <span class="keyword">char</span>* name; <span class="comment">//Java方法名</span></span><br><span class="line"> <span class="keyword">const</span> <span class="keyword">char</span>* signature; <span class="comment">//方法的参数和返回值,使用字符串记录,格式形如`()V, (I)I`,括号内表示函数参数,括号右侧表示函数返回值</span></span><br><span class="line"> <span class="keyword">void</span>* fnPtr; <span class="comment">// 指向JNI函数的函数指针</span></span><br><span class="line">} JNINativeMethod;</span><br></pre></td></tr></table></figure></li><li><p>数据类型映射</p><ul><li><p>基本数据类型</p><table><thead><tr><th>Java类型</th><th>Native类型</th><th>域描述符</th><th>补充</th></tr></thead><tbody><tr><td>boolean</td><td>jboolean</td><td>Z</td><td></td></tr><tr><td>byte</td><td>jbyte</td><td>B</td><td></td></tr><tr><td>char</td><td>jchar</td><td>C</td><td></td></tr><tr><td>short</td><td>jshort</td><td>S</td><td></td></tr><tr><td>int</td><td>jint</td><td>I</td><td></td></tr><tr><td>long</td><td>jlong</td><td>J</td><td></td></tr><tr><td>float</td><td>jfloat</td><td>F</td><td></td></tr><tr><td>double</td><td>jdouble</td><td>D</td><td></td></tr><tr><td>void</td><td>void</td><td>V</td><td></td></tr></tbody></table></li><li><p>数组引用类型</p><table><thead><tr><th>Java类型</th><th>Native类型</th><th>域描述符</th><th>补充</th></tr></thead><tbody><tr><td>boolean[]</td><td>jbooleanArray</td><td>[Z</td><td></td></tr><tr><td>byte[]</td><td>jbyteArray</td><td>[B</td><td></td></tr><tr><td>char[]</td><td>jcharArray</td><td>[C</td><td></td></tr><tr><td>short[]</td><td>jshortArray</td><td>[S</td><td></td></tr><tr><td>int[]</td><td>jintArray</td><td>[I</td><td></td></tr><tr><td>long[]</td><td>jlongArray</td><td>[J</td><td></td></tr><tr><td>float[]</td><td>jfloatArray</td><td>[F</td><td></td></tr><tr><td>double[]</td><td>jdoubleArray</td><td>[D</td><td></td></tr></tbody></table></li><li><p>对象引用类型</p><table><thead><tr><th>Java类型</th><th>Native类型</th><th>域描述符</th><th>补充</th></tr></thead><tbody><tr><td>Class</td><td>jobject</td><td>Lcom.example.Class;</td><td>以<code>"L"</code>开头,以<code>";"</code>结尾,内部类使用<code>"$"</code>连接,String除外</td></tr><tr><td>String</td><td>jstring</td><td>Ljava/lang/String;</td><td>唯一的例外</td></tr></tbody></table></li><li><p>对象数组引用类型</p><table><thead><tr><th>Java类型</th><th>Native类型</th><th>域描述符</th><th>补充</th></tr></thead><tbody><tr><td>Class</td><td>jobject</td><td>[Lcom.example.Class;</td><td>以<code>"[L"</code>开头,以<code>";"</code>结尾,内部类使用<code>"$"</code>连接,String除外</td></tr><tr><td>String</td><td>jstring</td><td>[Ljava/lang/String;</td><td>唯一的例外</td></tr></tbody></table></li></ul></li><li><p>JNI函数默认参数</p><ul><li><p>native方法默认参数<br>普通的native方法,是Java类的成员方法,默认的参数有以下两个</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">JNIEnv *env, jobject thiz</span><br></pre></td></tr></table></figure><ul><li><p><code>JNIEnv *env</code></p><p>指代当前的java环境,可以利用JNIEnv操作Java层代码</p></li><li><p><code>jobject thiz</code></p><p>指代JNI函数对应的java native方法对应的类的实例</p></li></ul></li><li><p>static native方法默认参数<br>static native方法,是Java类的static方法,默认的参数有以下两个</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">JNIEnv *env, jclass classz</span><br></pre></td></tr></table></figure><ul><li><p><code>JNIEnv *env</code></p><p>指代当前的java环境,可以利用JNIEnv操作Java层代码</p></li><li><p><code>jclass classz</code></p><p>指代JNI函数对应的java static native方法对应的class对象</p></li></ul></li></ul></li><li><p>native-lib.cpp</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><jni.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><string></span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 定义java层对应的package名称</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> JNIREG_CLASS <span class="meta-string">"com/example/MainActivity"</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Native方法实现</span></span><br><span class="line"><span class="function"><span class="keyword">static</span> jstring <span class="title">stringFromJNI</span><span class="params">(JNIEnv *env, jclass classz)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> std::string hello = <span class="string">"Hello from C++"</span>;</span><br><span class="line"> <span class="keyword">return</span> env-><span class="built_in">NewStringUTF</span>(hello.<span class="built_in">c_str</span>());</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// Java层和Native层的方法签名</span></span><br><span class="line"><span class="keyword">static</span> JNINativeMethod nativeMethods[] = {</span><br><span class="line"> {<span class="string">"stringFromJNI"</span>, <span class="string">"()Ljava/lang/String;"</span>, (jstring *)stringFromJNI},</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="comment">// 注册native方法</span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">register_native_methods</span><span class="params">(JNIEnv *env)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> jclass clazz = env-><span class="built_in">FindClass</span>(JNIREG_CLASS);</span><br><span class="line"> <span class="keyword">if</span> (clazz == <span class="literal">NULL</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="built_in">ALOGE</span>(<span class="string">"Native registeration unable to find class '%s'"</span>, JNIREG_CLASS);</span><br><span class="line"> <span class="keyword">return</span> JNI_FALSE;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (env-><span class="built_in">RegisterNatives</span>(clazz, nativeMethods, <span class="built_in"><span class="keyword">sizeof</span></span> (nativeMethods) / <span class="built_in"><span class="keyword">sizeof</span></span>(nativeMethods[<span class="number">0</span>])) < <span class="number">0</span>)</span><br><span class="line"> {</span><br><span class="line"> env-><span class="built_in">DeleteLocalRef</span>(clazz);</span><br><span class="line"> <span class="built_in">ALOGE</span>(<span class="string">"RegisterNatives failed for '%s'"</span>, JNIREG_CLASS);</span><br><span class="line"> <span class="keyword">return</span> JNI_FALSE;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> JNI_TRUE;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 重写JNI_OnLoad方法</span></span><br><span class="line"><span class="keyword">extern</span> <span class="string">"C"</span> <span class="function">JNIEXPORT jint JNICALL <span class="title">JNI_OnLoad</span><span class="params">(JavaVM *vm, <span class="keyword">void</span> *reserved)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> JNIEnv *env = <span class="literal">NULL</span>;</span><br><span class="line"> <span class="keyword">if</span> (vm-><span class="built_in">GetEnv</span>((<span class="keyword">void</span> **)&env, JNI_VERSION_1_6) != JNI_OK)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">return</span> JNI_ERR;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (JNI_TRUE != <span class="built_in">register_native_methods</span>(env))</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">return</span> JNI_ERR;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> JNI_VERSION_1_6;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure></li></ul><h2 id="两种注册方法的对比"><a href="#两种注册方法的对比" class="headerlink" title="两种注册方法的对比"></a>两种注册方法的对比</h2><table><thead><tr><th>注册方法</th><th>优点</th><th>缺点</th></tr></thead><tbody><tr><td>静态注册</td><td>支持自动生成的IDE,可以比较方便的编写代码</td><td>在没有IDE自动生成的情况下,编写不方便</td></tr><tr><td>静态注册</td><td></td><td>程序运行效率低,每次调用native函数时,需要根据函数名在JNI层搜索对应的本地函数,建立对应关系,比较耗时</td></tr><tr><td>动态注册</td><td>Native层方法和Java层实现简单的代码分离,降低耦合度</td><td>需要手动实现注册方法</td></tr><tr><td>动态注册</td><td>大量的Native方法,注册起来更加方便</td><td></td></tr></tbody></table><h2 id="native方法和static-native方法的区别"><a href="#native方法和static-native方法的区别" class="headerlink" title="native方法和static native方法的区别"></a>native方法和static native方法的区别</h2><p>在上面的默认参数一节中,我们已经提到了关于native方法和static native方法的一些区别</p><ul><li>静态注册时,IDE帮我们生成对应的方法,我们可以省去编写函数签名的操作。</li><li>动态注册时,函数签名需要我们自己编写,就需要知道native方法和static native方法的一些区别和差异,才能使得我们的函数能够正常运行。</li></ul><h2 id="常用的JNI方法"><a href="#常用的JNI方法" class="headerlink" title="常用的JNI方法"></a>常用的JNI方法</h2><ul><li>jclass获取jobject<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">jmethod methodId = env-><span class="built_in">GetMethodID</span>(classz, <span class="string">"<init>"</span>, <span class="string">"()V"</span>);</span><br><span class="line">jobject jobj = env-><span class="built_in">NewObject</span>(classz, methodId);</span><br></pre></td></tr></table></figure></li><li>jobject获取jclass<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jclass classz = env-><span class="built_in">GetObjectClass</span>(thiz);</span><br></pre></td></tr></table></figure></li><li>获取object的非静态字段<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 获取jclass,静态方法则不需要这步</span></span><br><span class="line">jclass classz = env-><span class="built_in">GetObjectClass</span>(thiz);</span><br><span class="line"><span class="comment">// 获取field id,</span></span><br><span class="line">jfieldID fid = env-><span class="built_in">GetFieldID</span>(classz, <span class="string">"mName"</span>, <span class="string">"Ljava/lang/String;"</span>);</span><br><span class="line"><span class="comment">// 获取field 值</span></span><br><span class="line">jstring mName = env-><span class="built_in">GetObjectField</span>(thiz, fid);</span><br><span class="line"><span class="comment">// 设置值</span></span><br><span class="line">std::string name = <span class="string">"myname"</span>;</span><br><span class="line">env-><span class="built_in">SetObjectField</span>(thiz, fid, env-><span class="built_in">NewStringUTF</span>(name.<span class="built_in">c_str</span>()))</span><br></pre></td></tr></table></figure></li><li>获取class的静态字段<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 获取jclass,静态方法则不需要这步</span></span><br><span class="line">jclass classz = env-><span class="built_in">GetObjectClass</span>(thiz);</span><br><span class="line"><span class="comment">// 获取field id,</span></span><br><span class="line">jfieldID fid = env-><span class="built_in">GetStaticFieldID</span>(classz, <span class="string">"sName"</span>, <span class="string">"Ljava/lang/String;"</span>);</span><br><span class="line"><span class="comment">// 获取field 值</span></span><br><span class="line">jstring mName = env-><span class="built_in">GetStaticObjectField</span>(thiz, fid);</span><br><span class="line"><span class="comment">// 设置值</span></span><br><span class="line">std::string name = <span class="string">"myname"</span>;</span><br><span class="line">env-><span class="built_in">SetStaticObjectField</span>(thiz, fid, env-><span class="built_in">NewStringUTF</span>(name.<span class="built_in">c_str</span>()))</span><br></pre></td></tr></table></figure></li><li>获取class的非静态方法<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 获取jclass,静态方法则不需要这步</span></span><br><span class="line">jclass classz = env-><span class="built_in">GetObjectClass</span>(thiz);</span><br><span class="line"><span class="comment">// 获取method id,</span></span><br><span class="line">jmethodID methodId = env-><span class="built_in">GetMethodID</span>(classz, <span class="string">"getName"</span>, <span class="string">"()Ljava/lang/String;"</span>);</span><br><span class="line"><span class="comment">// 调用java方法</span></span><br><span class="line">jstring name = env-><span class="built_in">CallObjectMethod</span>(thiz, methodId)</span><br></pre></td></tr></table></figure></li><li>获取class的静态方法<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 获取jclass,静态方法则不需要这步</span></span><br><span class="line">jclass classz = env-><span class="built_in">GetObjectClass</span>(thiz);</span><br><span class="line"><span class="comment">// 获取method id,</span></span><br><span class="line">jmethodID methodId = env-><span class="built_in">GetStaticMethodID</span>(classz, <span class="string">"getCount"</span>, <span class="string">"()I"</span>);</span><br><span class="line"><span class="comment">// 调用java方法</span></span><br><span class="line">jint count = env-><span class="built_in">CallStaticIntMethod</span>(thiz, methodId)</span><br></pre></td></tr></table></figure></li><li>访问构造方法<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 获取jclass,静态方法则不需要这步</span></span><br><span class="line">jclass classz = env-><span class="built_in">FindClass</span>(<span class="string">"java/util/Date"</span>);</span><br><span class="line">jmethod methodId = env-><span class="built_in">GetMethodID</span>(classz, <span class="string">"<init>"</span>, <span class="string">"()V"</span>);</span><br><span class="line"><span class="comment">// 实例化对象</span></span><br><span class="line">jobject date = env-><span class="built_in">NewObject</span>(classz, methodId);</span><br><span class="line"><span class="comment">// 获取调用方法ID</span></span><br><span class="line">jmethod getTimeId = env-><span class="built_in">GetMethodID</span>(classz, <span class="string">"getTime"</span>, <span class="string">"()J"</span>);</span><br><span class="line"><span class="comment">// 调用方法</span></span><br><span class="line">jlong time = env-><span class="built_in">CallLongMethod</span>(date, getTimeId);</span><br><span class="line">std::out<<<span class="string">"current time: "</span> << time <<endl;</span><br></pre></td></tr></table></figure></li></ul></div><footer class="post-footer"><div class="post-eof"></div></footer></article></div><div class="post-block"><article itemscope itemtype="http://schema.org/Article" class="post-content"><link itemprop="mainEntityOfPage" href="http://www.vectoros.club/post/67bab5c2.html"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="image" content="/uploads/avatar.webp"><meta itemprop="name" content="Vectoros"><meta itemprop="description" content=""></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="Keep Learning"></span><header class="post-header"><h2 class="post-title" itemprop="name headline"><a href="/post/67bab5c2.html" class="post-title-link" itemprop="url">Create a Native Service on Android P</a></h2><div class="post-meta-container"><div class="post-meta"><span class="post-meta-item"><span class="post-meta-item-icon"><i class="far fa-calendar"></i> </span><span class="post-meta-item-text">发表于</span> <time title="创建时间:2019-10-09 10:53:44" itemprop="dateCreated datePublished" datetime="2019-10-09T10:53:44+08:00">2019-10-09</time> </span><span class="post-meta-item"><span class="post-meta-item-icon"><i class="far fa-folder"></i> </span><span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/" itemprop="url" rel="index"><span itemprop="name">Android</span></a> </span>, <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/NDK/" itemprop="url" rel="index"><span itemprop="name">NDK</span></a> </span>, <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/NDK/Service/" itemprop="url" rel="index"><span itemprop="name">Service</span></a></span></span></div></div></header><div class="post-body" itemprop="articleBody"><p>在定制自己的Android嵌入式系统时候,有时我们需要创建一个Native Service用来和底层设备通信。</p><ul><li>Native Service其实是一个Linux守护进程,提供一些必要的服务。</li><li>Android提供了Binder进程间通信机制,Native Service就需要遵循Android的规则来实现</li></ul><h2 id="整体框架"><a href="#整体框架" class="headerlink" title="整体框架"></a>整体框架</h2><ul><li>Server (后台Service服务)</li><li>Client (提供和Service通信的接口)</li><li>JNI (持有一个Client端,封装对应的接口,用于和Service通信)</li><li>Java (JNI层提供给Java层的接口)</li><li>Selinux修改(Android 8以后)</li><li>预编译到系统中,供Framework调用(如何在framework.jar中调用我们自己生成的java接口)</li></ul><h2 id="代码实现框架"><a href="#代码实现框架" class="headerlink" title="代码实现框架"></a>代码实现框架</h2><p>代码我们以一个LED开关接口为例,添加一个NativeService,用来控制一个独立的LED灯的开关。</p><ul><li><p>创建组织代码目录</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># root directory</span></span><br><span class="line">mkdir LEDService</span><br><span class="line"><span class="built_in">cd</span> LEDService</span><br><span class="line"><span class="comment"># headers</span></span><br><span class="line">mkdir include</span><br><span class="line"><span class="comment"># hardware interface</span></span><br><span class="line">mkdir hal</span><br><span class="line"><span class="comment"># service implement</span></span><br><span class="line">mkdir service</span><br><span class="line"><span class="comment"># client test</span></span><br><span class="line">mkdir <span class="built_in">test</span></span><br><span class="line"><span class="comment"># JNI interface</span></span><br><span class="line">mkdir jni</span><br><span class="line"><span class="comment"># java interface</span></span><br><span class="line">mkdir java</span><br><span class="line"><span class="comment"># summary</span></span><br><span class="line">ls -l</span><br></pre></td></tr></table></figure><h2 id="编译脚本"><a href="#编译脚本" class="headerlink" title="编译脚本"></a>编译脚本</h2></li><li><p>为什么先写编译脚本?</p><ul><li>编译脚本可以预先帮助我们组织代码</li><li>我们可以提前知道需要编译输出什么</li></ul></li><li><p>我们需要生成哪几个文件</p><ul><li>libledservice.so 共享库,提供给Server端和Client端调用</li><li>libledservicemanager_jni.so JNI共享库,供Java接口调用</li><li>ledservicemanager.jar Jar包,提供给其他java层调用</li><li>ledservice.rc 服务启动的rc文件</li><li>com.vectoros.led.xml permission文件</li></ul></li><li><p>Android.mk</p><p>我们在LEDService目录下创建一个Android.mk用于编译C/C++ so, 可执行文件以及rc,xml等资源文件的编译输出。</p><figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">################ LIB_LED_SERVICE ############</span></span><br><span class="line"><span class="keyword">include</span> <span class="variable">$(CLEAR_VARS)</span></span><br><span class="line">LOCAL_MODULE:= libledservice</span><br><span class="line"></span><br><span class="line">LOCAL_SRC_FILES:= \</span><br><span class="line"> service/LEDService.cpp \</span><br><span class="line"> service/ILEDService.cpp \</span><br><span class="line"> service/LEDServiceManager.cpp</span><br><span class="line"></span><br><span class="line">LOCAL_C_INCLUDES += \</span><br><span class="line"> <span class="variable">$(LOCAL_PATH)</span>/<span class="keyword">include</span></span><br><span class="line"></span><br><span class="line">LOCAL_SHARED_LIBRARIES := \</span><br><span class="line"> libbinder \</span><br><span class="line"> libutils \</span><br><span class="line"> libcutils \</span><br><span class="line"> liblog</span><br><span class="line"></span><br><span class="line"><span class="comment"># Export include dir</span></span><br><span class="line">LOCAL_EXPORT_C_INCLUDE_DIRS := <span class="variable">$(LOCAL_PATH)</span>/<span class="keyword">include</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># LOCAL_CFLAGS += -mhard-float</span></span><br><span class="line"><span class="comment"># LOCAL_LDFLAGS += -Wl,--no-warn-mismatch</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">include</span> <span class="variable">$(BUILD_SHARED_LIBRARY)</span></span><br><span class="line"></span><br><span class="line"><span class="comment">################ LED_SERVICE ############</span></span><br><span class="line"><span class="keyword">include</span> <span class="variable">$(CLEAR_VARS)</span></span><br><span class="line">LOCAL_MODULE:= ledservice</span><br><span class="line"></span><br><span class="line">LOCAL_SRC_FILES:= \</span><br><span class="line"> service/main_ledservice.cpp </span><br><span class="line"></span><br><span class="line">LOCAL_SHARED_LIBRARIES := \</span><br><span class="line"> libutils \</span><br><span class="line"> liblog \</span><br><span class="line"> libbinder \</span><br><span class="line"> libledservice</span><br><span class="line"></span><br><span class="line">LOCAL_MODULE_CLASS := EXECUTABLES</span><br><span class="line">LOCAL_INIT_RC := service/ledservice.rc</span><br><span class="line"><span class="keyword">include</span> <span class="variable">$(BUILD_EXECUTABLE)</span></span><br><span class="line"></span><br><span class="line"><span class="comment">################ LED_SERVICE_MANAGER_JNI ############</span></span><br><span class="line"><span class="keyword">include</span> <span class="variable">$(CLEAR_VARS)</span></span><br><span class="line">LOCAL_MODULE:= libledservicemanager_jni</span><br><span class="line"></span><br><span class="line">LOCAL_SRC_FILES:= \</span><br><span class="line"> jni/com_vectoros_ledservice_manager_jni.cpp </span><br><span class="line"></span><br><span class="line">LOCAL_SHARED_LIBRARIES := \</span><br><span class="line"> libutils \</span><br><span class="line"> liblog \</span><br><span class="line"> libcutils \</span><br><span class="line"> libledservice \</span><br><span class="line"> libbinder</span><br><span class="line"></span><br><span class="line">LOCAL_CFLAGS += -Wno-unused-parameter</span><br><span class="line">LOCAL_LDFLAGS += -Wl,--no-warn-mismatch</span><br><span class="line"></span><br><span class="line"><span class="keyword">include</span> <span class="variable">$(BUILD_SHARED_LIBRARY)</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Using Android.bp to build java library</span></span><br><span class="line"><span class="comment"># ################# JAVA_LIBRARIES ############</span></span><br><span class="line"><span class="comment"># include $(CLEAR_VARS)</span></span><br><span class="line"><span class="comment"># LOCAL_MODULE:= ledservicemanager</span></span><br><span class="line"><span class="comment"># LOCAL_SRC_FILES:= \</span></span><br><span class="line"><span class="comment"># $(call all-java-files-under,java)</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># LOCAL_MODULE_TAGS := optional</span></span><br><span class="line"><span class="comment"># LOCAL_NO_STANDARD_LIBRARIES := true</span></span><br><span class="line"><span class="comment"># LOCAL_DX_FLAGS := --core-library</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># include $(BUILD_JAVA_LIBRARY)</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ################ PERMISION_FILES ############</span></span><br><span class="line"><span class="keyword">include</span> <span class="variable">$(CLEAR_VARS)</span></span><br><span class="line">LOCAL_MODULE:= com.vectoros.led.xml</span><br><span class="line">LOCAL_MODULE_TAGS := optional</span><br><span class="line">LOCAL_MODULE_CLASS:= ETC</span><br><span class="line"></span><br><span class="line">LOCAL_SRC_FILES:= java/<span class="variable">$(LOCAL_MODULE)</span></span><br><span class="line">LOCAL_MODULE_PATH := <span class="variable">$(TARGET_OUT_ETC)</span>/permissions</span><br><span class="line"><span class="keyword">include</span> <span class="variable">$(BUILD_PREBUILT)</span></span><br><span class="line"></span><br><span class="line"><span class="comment">################ CMD_TEST_CLIENT ############</span></span><br><span class="line"><span class="keyword">include</span> <span class="variable">$(CLEAR_VARS)</span></span><br><span class="line">LOCAL_MODULE:= ledserviceclient</span><br><span class="line"></span><br><span class="line">LOCAL_SRC_FILES:= \</span><br><span class="line"> test/main_ledservice_client.cpp</span><br><span class="line"></span><br><span class="line">LOCAL_SHARED_LIBRARIES := \</span><br><span class="line"> libbinder \</span><br><span class="line"> libutils \</span><br><span class="line"> libcutils \</span><br><span class="line"> liblog \</span><br><span class="line"> libledservice</span><br><span class="line"></span><br><span class="line">LOCAL_LDFLAGS += -Wl,--no-warn-mismatch</span><br><span class="line">LOCAL_MODULE_CLASS := EXECUTABLES</span><br><span class="line"><span class="keyword">include</span> <span class="variable">$(BUILD_EXECUTABLE)</span></span><br></pre></td></tr></table></figure></li><li><p>Andorid.bp</p><p>我们在java目录下,创建一个Android.bp文件,用于生成jar包。至于为什么必须要用Android.bp,会留在集成到framework里面的时候讲。</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">java_library {</span><br><span class="line"> name: "ledservicemanager",</span><br><span class="line"> srcs: [</span><br><span class="line"> "com/vectoros/led/*.java",</span><br><span class="line"> ],</span><br><span class="line"></span><br><span class="line"> hostdex: true,</span><br><span class="line"> java_version: "1.7",</span><br><span class="line"> no_framework_libs: true,</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p>总结</p><p>通过以上的编译脚本,我们知道了自己需要写哪些文件,会生成什么样的文件,接下来就可以往下写实现部分的代码了。</p></li></ul><h2 id="头文件实现"><a href="#头文件实现" class="headerlink" title="头文件实现"></a>头文件实现</h2><ul><li><p>主要有三个头文件</p><ul><li>LEDService.h</li><li>LEDServiceManager.h</li><li>ILEDService.h</li></ul></li><li><p>ILEDService.h</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">ifndef</span> ANDROID_ILED_NATIVE_SERVICE_H</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> ANDROID_ILED_NATIVE_SERVICE_H</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdint.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/types.h></span></span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><utils/RefBase.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><utils/Singleton.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><utils/Errors.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><utils/String16.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><binder/IInterface.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> android</span><br><span class="line">{</span><br><span class="line"></span><br><span class="line"> <span class="class"><span class="keyword">class</span> <span class="title">ILEDService</span> :</span> <span class="keyword">public</span> IInterface</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">public</span>:</span><br><span class="line"> <span class="built_in">DECLARE_META_INTERFACE</span>(LEDService);</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">virtual</span> <span class="keyword">int</span> <span class="title">initHardware</span><span class="params">(<span class="keyword">void</span>)</span> </span>= <span class="number">0</span>;</span><br><span class="line"> <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">releaseHardware</span><span class="params">(<span class="keyword">void</span>)</span> </span>= <span class="number">0</span>;</span><br><span class="line"> <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">on</span><span class="params">(<span class="keyword">void</span>)</span> </span>= <span class="number">0</span>;</span><br><span class="line"> <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">off</span><span class="params">(<span class="keyword">void</span>)</span> </span>= <span class="number">0</span>;</span><br><span class="line"> };</span><br><span class="line"></span><br><span class="line"> <span class="class"><span class="keyword">class</span> <span class="title">BnLEDService</span> :</span> <span class="keyword">public</span> BnInterface<ILEDService>{</span><br><span class="line"> <span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">virtual</span> <span class="keyword">status_t</span> <span class="title">onTransact</span><span class="params">(<span class="keyword">uint32_t</span> code, <span class="keyword">const</span> Parcel& data,</span></span></span><br><span class="line"><span class="function"><span class="params"> Parcel* reply, <span class="keyword">uint32_t</span> flags = <span class="number">0</span>)</span></span>;</span><br><span class="line"> };</span><br><span class="line"></span><br><span class="line"> <span class="class"><span class="keyword">enum</span> <span class="title">LED_SERVICE_TYPE</span>{</span></span><br><span class="line"> BASE_START,</span><br><span class="line"> ON,</span><br><span class="line"> OFF,</span><br><span class="line"> };</span><br><span class="line"> </span><br><span class="line">} <span class="comment">// namespace android</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span> <span class="comment">//ANDROID_ILED_NATIVE_SERVICE_H</span></span></span><br></pre></td></tr></table></figure></li><li><p>LEDService.h</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">ifndef</span> ANDROID_LED_NATIVE_SERVICE_H</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> ANDROID_LED_NATIVE_SERVICE_H</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><map></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdint.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/types.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cutils/compiler.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><utils/Atomic.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><utils/Errors.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><utils/KeyedVector.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><utils/RefBase.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><utils/SortedVector.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><utils/threads.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><binder/BinderService.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"ILEDService.h"</span></span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> android {</span><br><span class="line"></span><br><span class="line"> <span class="class"><span class="keyword">class</span> <span class="title">LEDService</span> :</span> <span class="keyword">public</span> BinderService<LEDService>, <span class="keyword">public</span> BnLEDService</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">static</span> <span class="keyword">char</span> <span class="keyword">const</span>* <span class="title">getServiceName</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"LEDService"</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="built_in">LEDService</span>();</span><br><span class="line"> ~<span class="built_in">LEDService</span>();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span>:</span><br><span class="line"> <span class="function"><span class="keyword">virtual</span> <span class="keyword">int</span> <span class="title">initHardware</span><span class="params">(<span class="keyword">void</span>)</span></span>;</span><br><span class="line"> <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">releaseHardware</span><span class="params">(<span class="keyword">void</span>)</span></span>;</span><br><span class="line"> <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">on</span><span class="params">(<span class="keyword">void</span>)</span></span>;</span><br><span class="line"> <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">off</span><span class="params">(<span class="keyword">void</span>)</span></span>;</span><br><span class="line"> };</span><br><span class="line">}; <span class="comment">// namespace android</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span> <span class="comment">// ANDROID_LED_NATIVE_SERVICE_H</span></span></span><br></pre></td></tr></table></figure></li><li><p>LEDServiceManager.h</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">ifndef</span> ANDROID_LED_NATIVE_MANAGER_H</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> ANDROID_LED_NATIVE_MANAGER_H</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdint.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/types.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><binder/IBinder.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><utils/RefBase.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><utils/Singleton.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><utils/threads.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"ILEDService.h"</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> android</span><br><span class="line">{</span><br><span class="line"> <span class="class"><span class="keyword">class</span> <span class="title">LEDServiceManager</span> :</span> <span class="keyword">public</span> Singleton<LEDServiceManager></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">private</span>:</span><br><span class="line"> <span class="comment">/* data */</span></span><br><span class="line"> <span class="keyword">bool</span> isDied;</span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">ledServiceDied</span><span class="params">()</span></span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">mutable</span> sp<ILEDService> mLEDService;</span><br><span class="line"> <span class="keyword">mutable</span> sp<IBinder::DeathRecipient> mDeathObserver;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span>:</span><br><span class="line"> <span class="built_in">LEDServiceManager</span>(<span class="comment">/* args */</span>);</span><br><span class="line"> ~<span class="built_in">LEDServiceManager</span>();</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">initHardware</span><span class="params">(<span class="keyword">void</span>)</span></span>;</span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">releaseHardware</span><span class="params">(<span class="keyword">void</span>)</span></span>;</span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">on</span><span class="params">(<span class="keyword">void</span>)</span></span>;</span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">off</span><span class="params">(<span class="keyword">void</span>)</span></span>;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">status_t</span> <span class="title">assertState</span><span class="params">()</span></span>;</span><br><span class="line"> <span class="function"><span class="keyword">bool</span> <span class="title">checkService</span><span class="params">()</span> <span class="keyword">const</span></span>;</span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">resetServiceStatus</span><span class="params">()</span></span>;</span><br><span class="line"> };</span><br><span class="line">} <span class="comment">// namespace android</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span> <span class="comment">//ANDROID_LED_NATIVE_MANAGER_H</span></span></span><br></pre></td></tr></table></figure></li></ul><h2 id="客户端和服务端实现"><a href="#客户端和服务端实现" class="headerlink" title="客户端和服务端实现"></a>客户端和服务端实现</h2><ul><li>ILEDService.cpp<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdint.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><malloc.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/types.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><binder/Parcel.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><binder/IMemory.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><binder/IPCThreadState.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><binder/IServiceManager.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"ILEDService.h"</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> __ANDROID__</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> LOG_TAG <span class="meta-string">"ILEDService"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">if</span> ANDROID_API_LEVEL >= 26</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><log/log.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">else</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cutils/log.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> android</span><br><span class="line">{</span><br><span class="line"> <span class="class"><span class="keyword">enum</span>{</span></span><br><span class="line"> INIT_HARDWARE = IBinder::FIRST_CALL_TRANSACTION,</span><br><span class="line"> RELEASE_HARDWARE,</span><br><span class="line"> ON,</span><br><span class="line"> OFF,</span><br><span class="line"> };</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="class"><span class="keyword">class</span> <span class="title">BpLEDService</span> :</span> <span class="keyword">public</span> BpInterface<ILEDService></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">public</span>:</span><br><span class="line"> <span class="built_in">BpLEDService</span>(<span class="keyword">const</span> sp<IBinder>& impl) : BpInterface<ILEDService>(impl)</span><br><span class="line"> {</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">initHardware</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> Parcel data, reply;</span><br><span class="line"> data.<span class="built_in">writeInterfaceToken</span>(ILEDService::<span class="built_in">getInterfaceDescriptor</span>());</span><br><span class="line"> <span class="built_in">remote</span>()-><span class="built_in">transact</span>(INIT_HARDWARE, data, &reply);</span><br><span class="line"> <span class="keyword">return</span> (<span class="keyword">int</span>)reply.<span class="built_in">readInt32</span>();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">releaseHardware</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> Parcel data, reply;</span><br><span class="line"> data.<span class="built_in">writeInterfaceToken</span>(ILEDService::<span class="built_in">getInterfaceDescriptor</span>());</span><br><span class="line"> <span class="built_in">remote</span>()-><span class="built_in">transact</span>(RELEASE_HARDWARE, data, &reply);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">on</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> Parcel data, reply;</span><br><span class="line"> data.<span class="built_in">writeInterfaceToken</span>(ILEDService::<span class="built_in">getInterfaceDescriptor</span>());</span><br><span class="line"> <span class="built_in">remote</span>()-><span class="built_in">transact</span>(ON, data, &reply);</span><br><span class="line"> <span class="keyword">return</span> (<span class="keyword">int</span>) reply.<span class="built_in">readInt32</span>();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">off</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> Parcel data, reply;</span><br><span class="line"> data.<span class="built_in">writeInterfaceToken</span>(ILEDService::<span class="built_in">getInterfaceDescriptor</span>());</span><br><span class="line"> <span class="built_in">remote</span>()-><span class="built_in">transact</span>(OFF, data, &reply);</span><br><span class="line"> <span class="keyword">return</span> (<span class="keyword">int</span>) reply.<span class="built_in">readInt32</span>();</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"></span><br><span class="line"> <span class="built_in">IMPLEMENT_META_INTERFACE</span>(LEDService, <span class="string">"android.vectoros.LEDService"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">status_t</span> <span class="title">BnLEDService::onTransact</span><span class="params">(<span class="keyword">uint32_t</span> code, <span class="keyword">const</span> Parcel& data, Parcel* reply, <span class="keyword">uint32_t</span> flags)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">char</span> *buff;</span><br><span class="line"> <span class="keyword">int</span> len, retval;</span><br><span class="line"> <span class="keyword">status_t</span> status;</span><br><span class="line"> </span><br><span class="line"> <span class="built_in"><span class="keyword">switch</span></span>(code) {</span><br><span class="line"> <span class="keyword">case</span> INIT_HARDWARE:{</span><br><span class="line"> <span class="built_in">CHECK_INTERFACE</span>(ILEDService, data, reply);</span><br><span class="line"> retval = <span class="built_in">initHardware</span>();</span><br><span class="line"> reply-><span class="built_in">writeInt32</span>(retval); </span><br><span class="line"> <span class="keyword">return</span> NO_ERROR;</span><br><span class="line"> } <span class="keyword">break</span>;</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"> <span class="keyword">case</span> RELEASE_HARDWARE:{</span><br><span class="line"> <span class="built_in">CHECK_INTERFACE</span>(ILEDService, data, reply); </span><br><span class="line"> <span class="built_in">releaseHardware</span>();</span><br><span class="line"> <span class="keyword">return</span> NO_ERROR;</span><br><span class="line"> } <span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">case</span> ON:{</span><br><span class="line"> <span class="built_in">CHECK_INTERFACE</span>(ILEDService, data, reply);</span><br><span class="line"> <span class="built_in">on</span>();</span><br><span class="line"> <span class="keyword">return</span> NO_ERROR;</span><br><span class="line"> } <span class="keyword">break</span>;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">case</span> OFF:{</span><br><span class="line"> <span class="built_in">CHECK_INTERFACE</span>(ILEDService, data, reply);</span><br><span class="line"> <span class="built_in">off</span>();</span><br><span class="line"> <span class="keyword">return</span> NO_ERROR;</span><br><span class="line"> } <span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">default</span>:</span><br><span class="line"> <span class="keyword">return</span> BBinder::<span class="built_in">onTransact</span>(code, data, reply, flags);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">} <span class="comment">// namespace android</span></span><br></pre></td></tr></table></figure></li><li>LEDService.cpp<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdint.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><math.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/types.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><utils/Errors.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><utils/RefBase.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><utils/Singleton.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><utils/String16.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><binder/BinderService.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><binder/IServiceManager.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"LEDService.h"</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> BUFFER_SIZE 512</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> __ANDROID__</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> LOG_TAG <span class="meta-string">"LEDService"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">if</span> ANDROID_API_LEVEL >= 26</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><log/log.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">else</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cutils/log.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> android {</span><br><span class="line"></span><br><span class="line">LEDService::<span class="built_in">LEDService</span>()</span><br><span class="line">{</span><br><span class="line"> <span class="built_in">ALOGI</span>(<span class="string">"LEDService()"</span>); </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">LEDService::~<span class="built_in">LEDService</span>(){</span><br><span class="line"> <span class="built_in">ALOGI</span>(<span class="string">"~LEDService()"</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">LEDService::initHardware</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="built_in">ALOGI</span>(<span class="string">"initHardware(), check camera env."</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">LEDService::releaseHardware</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="built_in">ALOGI</span>(<span class="string">"releaseHardware()"</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">LEDService::on</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="built_in">ALOGI</span>(<span class="string">"on()"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">LEDService::off</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="built_in">ALOGI</span>(<span class="string">"off()"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">}; <span class="comment">// namespace android</span></span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li>LEDServiceManager.cpp<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdint.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/types.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><utils/Errors.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><utils/RefBase.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><utils/Singleton.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> __ANDROID__</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> LOG_TAG <span class="meta-string">"LEDServiceManager"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">if</span> ANDROID_API_LEVEL >= 26</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><log/log.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">else</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cutils/log.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><binder/IBinder.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><binder/IServiceManager.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"ILEDService.h"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"LEDServiceManager.h"</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> android</span><br><span class="line">{</span><br><span class="line"> LEDServiceManager::<span class="built_in">LEDServiceManager</span>() : <span class="built_in">isDied</span>(<span class="literal">false</span>)</span><br><span class="line"> {</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> LEDServiceManager::~<span class="built_in">LEDServiceManager</span>()</span><br><span class="line"> {</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">LEDServiceManager::LEDServiceDied</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> isDied = <span class="literal">true</span>;</span><br><span class="line"> mLEDService.<span class="built_in">clear</span>();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">status_t</span> <span class="title">LEDServiceManager::assertState</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (mLEDService == <span class="literal">NULL</span>) {</span><br><span class="line"> <span class="comment">// try for one second</span></span><br><span class="line"> <span class="function"><span class="keyword">const</span> String16 <span class="title">name</span><span class="params">(<span class="string">"LEDService"</span>)</span></span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i=<span class="number">0</span> ; i<<span class="number">4</span> ; i++) {</span><br><span class="line"> <span class="keyword">status_t</span> err = <span class="built_in">getService</span>(name, &mLEDService);</span><br><span class="line"> <span class="keyword">if</span> (err == NAME_NOT_FOUND) {</span><br><span class="line"> <span class="built_in">usleep</span>(<span class="number">250000</span>);</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (err != NO_ERROR) {</span><br><span class="line"> <span class="built_in">ALOGE</span>(<span class="string">"LEDService not found"</span>);</span><br><span class="line"> <span class="keyword">return</span> err;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="built_in">initLEDServiceNative</span>();</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"> <span class="class"><span class="keyword">class</span> <span class="title">DeathObserver</span> :</span> <span class="keyword">public</span> IBinder::DeathRecipient {</span><br><span class="line"> LEDServiceManager& mLEDServiceManager;</span><br><span class="line"> <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">binderDied</span><span class="params">(<span class="keyword">const</span> wp<IBinder>& who)</span> </span>{</span><br><span class="line"> <span class="built_in">ALOGW</span>(<span class="string">"LEDService died [%p]"</span>, who.<span class="built_in">unsafe_get</span>());</span><br><span class="line"> mLEDServiceManager.<span class="built_in">LEDServiceDied</span>();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">public</span>:</span><br><span class="line"> <span class="built_in">DeathObserver</span>(LEDServiceManager& mgr) : <span class="built_in">mLEDServiceManager</span>(mgr) { }</span><br><span class="line"> };</span><br><span class="line"> </span><br><span class="line"> mDeathObserver = <span class="keyword">new</span> <span class="built_in">DeathObserver</span>(*<span class="keyword">const_cast</span><LEDServiceManager *>(<span class="keyword">this</span>));</span><br><span class="line"> mLEDService-><span class="built_in">asBinder</span>(mLEDService)-><span class="built_in">linkToDeath</span>(mDeathObserver);</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">return</span> NO_ERROR;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="function"><span class="keyword">bool</span> <span class="title">LEDServiceManager::checkService</span><span class="params">()</span> <span class="keyword">const</span> </span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">return</span> isDied? <span class="literal">true</span>:<span class="literal">false</span>;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">LEDServiceManager::resetServiceStatus</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> isDied = <span class="literal">false</span>; </span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">LEDServiceManager::initHardware</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">return</span> mLEDService-><span class="built_in">initHardware</span>(); </span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">LEDServiceManager::releaseHardware</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> mLEDService-><span class="built_in">releaseHardware</span>();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">LEDServiceManager::on</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">return</span> mLEDService-><span class="built_in">on</span>();</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">LEDServiceManager::off</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">return</span> mLEDService-><span class="built_in">off</span>();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">} <span class="comment">// namespace android</span></span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li>main_LED_service.cpp<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><binder/BinderService.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><LEDService.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><binder/IPCThreadState.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><binder/ProcessState.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><binder/IServiceManager.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"ILEDService.h"</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> android;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span>** argv)</span> </span>{</span><br><span class="line"><span class="meta">#<span class="meta-keyword">if</span> 1</span></span><br><span class="line"> LEDService::<span class="built_in">publishAndJoinThreadPool</span>(<span class="literal">true</span>);</span><br><span class="line"> <span class="comment">// Like the SurfaceFlinger, limit the number of binder threads to 4.</span></span><br><span class="line"> ProcessState::<span class="built_in">self</span>()-><span class="built_in">setThreadPoolMaxThreadCount</span>(<span class="number">4</span>);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">else</span></span></span><br><span class="line"> </span><br><span class="line"> <span class="function">sp<ProcessState> <span class="title">proc</span><span class="params">(ProcessState::self())</span></span>;</span><br><span class="line"></span><br><span class="line"> sp<IServiceManager> sm = <span class="built_in">defaultServiceManager</span>();</span><br><span class="line"></span><br><span class="line"> sm-><span class="built_in">addService</span>(<span class="built_in">String16</span>(<span class="string">"LEDService"</span>), <span class="keyword">new</span> <span class="built_in">LEDService</span>());</span><br><span class="line"></span><br><span class="line"> ProcessState::<span class="built_in">self</span>()-><span class="built_in">startThreadPool</span>();</span><br><span class="line"> ProcessState::<span class="built_in">self</span>()-><span class="built_in">giveThreadPoolName</span>();</span><br><span class="line"> IPCThreadState::<span class="built_in">self</span>()-><span class="built_in">joinThreadPool</span>();</span><br><span class="line"> ProcessState::<span class="built_in">self</span>()-><span class="built_in">setThreadPoolMaxThreadCount</span>(<span class="number">4</span>);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul><h2 id="客户端服务端测试程序"><a href="#客户端服务端测试程序" class="headerlink" title="客户端服务端测试程序"></a>客户端服务端测试程序</h2><h2 id="JNI接口"><a href="#JNI接口" class="headerlink" title="JNI接口"></a>JNI接口</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br></pre></td><td class="code"><pre><span class="line">#include <jni.h></span><br><span class="line">#include <cstdio></span><br><span class="line">#include <map></span><br><span class="line">#include <stdlib.h></span><br><span class="line">#include <string.h></span><br><span class="line"></span><br><span class="line">#include "LEDServiceManager.h"</span><br><span class="line"></span><br><span class="line">#ifdef __ANDROID__</span><br><span class="line">#define LOG_TAG "LEDServiceManagerJNI"</span><br><span class="line">#if ANDROID_API_LEVEL >= 26</span><br><span class="line">#include <log/log.h></span><br><span class="line">#else</span><br><span class="line">#include <cutils/log.h></span><br><span class="line">#endif</span><br><span class="line">#endif</span><br><span class="line"></span><br><span class="line">#define JNIREG_CLASS "com/vectoros/led/LEDServiceManager"</span><br><span class="line"></span><br><span class="line">namespace android</span><br><span class="line">{</span><br><span class="line">static jint nativeOn(JNIEnv *env, jclass jcls)</span><br><span class="line">{</span><br><span class="line"> int err;</span><br><span class="line"> if (ledmgr)</span><br><span class="line"> {</span><br><span class="line"> err = ledmgr->assertState();</span><br><span class="line"> if (err == NO_ERROR)</span><br><span class="line"> {</span><br><span class="line"> return ledmgr->on();</span><br><span class="line"> }</span><br><span class="line"> else</span><br><span class="line"> {</span><br><span class="line"> return err;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> else</span><br><span class="line"> {</span><br><span class="line"> ALOGE("ledmgr is not init!\n");</span><br><span class="line"> return NO_INIT;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">static jint nativeOff(JNIEnv *env, jclass jcls)</span><br><span class="line">{</span><br><span class="line"> int err;</span><br><span class="line"> if (ledmgr)</span><br><span class="line"> {</span><br><span class="line"> err = ledmgr->assertState();</span><br><span class="line"> if (err == NO_ERROR)</span><br><span class="line"> {</span><br><span class="line"> return ledmgr->off();</span><br><span class="line"> }</span><br><span class="line"> else</span><br><span class="line"> {</span><br><span class="line"> return err;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> else</span><br><span class="line"> {</span><br><span class="line"> ALOGE("ledmgr is not init!\n");</span><br><span class="line"> return NO_INIT;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">static JNINativeMethod nativeMethods[] = {</span><br><span class="line"> {"nativeOn", "()I", (jint *)nativeOn},</span><br><span class="line"> {"nativeOff", "()I", (jint *)nativeOff},</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line">int register_vectoros_LEDService(JNIEnv *env)</span><br><span class="line">{</span><br><span class="line"> jclass clazz = env->FindClass(JNIREG_CLASS);</span><br><span class="line"> if (clazz == NULL)</span><br><span class="line"> {</span><br><span class="line"> ALOGE("Native registeration unable to find class '%s'", JNIREG_CLASS);</span><br><span class="line"> return JNI_FALSE;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> if (env->RegisterNatives(clazz, nativeMethods, sizeof(nativeMethods) / sizeof(nativeMethods[0])) < 0)</span><br><span class="line"> {</span><br><span class="line"> env->DeleteLocalRef(clazz);</span><br><span class="line"> ALOGE("RegisterNatives failed for '%s'", JNIREG_CLASS);</span><br><span class="line"> return JNI_FALSE;</span><br><span class="line"> }</span><br><span class="line"> return JNI_TRUE;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">} // namespace android</span><br><span class="line"></span><br><span class="line">using namespace android;</span><br><span class="line"></span><br><span class="line">extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)</span><br><span class="line">{</span><br><span class="line"> JNIEnv *env = NULL;</span><br><span class="line"> if (vm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK)</span><br><span class="line"> {</span><br><span class="line"> return JNI_ERR;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> ALOG_ASSERT(env, "Could not retrieve the env!");</span><br><span class="line"></span><br><span class="line"> if (JNI_TRUE != register_vectoros_LEDService(env))</span><br><span class="line"> {</span><br><span class="line"> return JNI_ERR;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> return JNI_VERSION_1_6;</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="Java接口"><a href="#Java接口" class="headerlink" title="Java接口"></a>Java接口</h2><ul><li>LEDServiceManager.java<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.vectoros.led;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LEDServiceManager</span></span>{</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> String TAG = <span class="string">"LEDServiceManager"</span>;</span><br><span class="line"> <span class="keyword">static</span>{</span><br><span class="line"> System.loadLibrary(<span class="string">"LEDServiceManager_jni"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">on</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="keyword">return</span> nativeOn();</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">off</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="keyword">return</span> nativeOff();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">native</span> <span class="keyword">int</span> <span class="title">nativeOn</span><span class="params">()</span></span>;</span><br><span class="line"> <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">native</span> <span class="keyword">int</span> <span class="title">nativeOff</span><span class="params">()</span></span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul></div><footer class="post-footer"><div class="post-eof"></div></footer></article></div><div class="post-block"><article itemscope itemtype="http://schema.org/Article" class="post-content"><link itemprop="mainEntityOfPage" href="http://www.vectoros.club/post/af4251a0.html"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="image" content="/uploads/avatar.webp"><meta itemprop="name" content="Vectoros"><meta itemprop="description" content=""></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="Keep Learning"></span><header class="post-header"><h2 class="post-title" itemprop="name headline"><a href="/post/af4251a0.html" class="post-title-link" itemprop="url">Compiler OpenCV under the NDK toolchain</a></h2><div class="post-meta-container"><div class="post-meta"><span class="post-meta-item"><span class="post-meta-item-icon"><i class="far fa-calendar"></i> </span><span class="post-meta-item-text">发表于</span> <time title="创建时间:2019-10-08 10:56:00" itemprop="dateCreated datePublished" datetime="2019-10-08T10:56:00+08:00">2019-10-08</time> </span><span class="post-meta-item"><span class="post-meta-item-icon"><i class="far fa-folder"></i> </span><span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/" itemprop="url" rel="index"><span itemprop="name">Android</span></a> </span>, <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/NDK/" itemprop="url" rel="index"><span itemprop="name">NDK</span></a> </span>, <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/NDK/OpenCV/" itemprop="url" rel="index"><span itemprop="name">OpenCV</span></a></span></span></div></div></header><div class="post-body" itemprop="articleBody"><h2 id="为什么要手动编译OpenCV"><a href="#为什么要手动编译OpenCV" class="headerlink" title="为什么要手动编译OpenCV"></a>为什么要手动编译OpenCV</h2><p>正常情况下,我们利用OpenCV来开发Android应用,使用预编译的so和jar包已经足够了,但是在某些特殊情形下,我们希望自己编译OpenCV,借此来提高OpenCV的性能。</p><h2 id="准备条件"><a href="#准备条件" class="headerlink" title="准备条件"></a>准备条件</h2><ol><li>Ubuntu 18.04 64Bit</li><li>cmake</li><li><a target="_blank" rel="noopener" href="https://dl.google.com/android/repository/android-ndk-r17c-linux-x86_64.zip">NDK Reversion 17.2.4988734</a></li><li><a target="_blank" rel="noopener" href="https://opencv.org/releases/">OpenCV 4.0.1</a></li><li>Android API</li><li>Target armeabi-v7a</li></ol><h2 id="下载和配置NDK"><a href="#下载和配置NDK" class="headerlink" title="下载和配置NDK"></a>下载和配置NDK</h2><ol><li><p>从Google官网下载</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wget https://dl.google.com/android/repository/android-ndk-r17c-linux-x86_64.zip</span><br></pre></td></tr></table></figure></li><li><p>下载后解压到特定目录</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">unzip android-ndk-r17c-linux-x86_64.zip</span><br><span class="line">mv android-ndk-r17c /opt/ndk</span><br></pre></td></tr></table></figure></li></ol><h2 id="下载OpenCV源码"><a href="#下载OpenCV源码" class="headerlink" title="下载OpenCV源码"></a>下载OpenCV源码</h2><ol><li><p>从官网下载最新版本或者特定版本</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">unzip opencv.zip</span><br></pre></td></tr></table></figure></li><li><p>从Github上下载</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> https://github.com/opencv/opencv.git opencv</span><br></pre></td></tr></table></figure></li></ol><h2 id="编译OpenCV"><a href="#编译OpenCV" class="headerlink" title="编译OpenCV"></a>编译OpenCV</h2><ol><li><p>创建输出目录</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ <span class="built_in">cd</span> opencv</span><br><span class="line">$ make build</span><br><span class="line">$ <span class="built_in">cd</span> build</span><br></pre></td></tr></table></figure></li><li><p>配置编译规则</p><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">cmake -DCMAKE_TOOLCHAIN_FILE=/opt/ndk/build/cmake/android.toolchain.cmake \</span><br><span class="line">-DANDROID_NDK=/opt/ndk \</span><br><span class="line">-DANDROID_NATIVE_API_LEVEL=android-<span class="number">21</span> \</span><br><span class="line">-DCMAKE_BUILD_TYPE=Release \</span><br><span class="line">-DENABLE_VFPV3=<span class="keyword">ON</span> \</span><br><span class="line">-DANDROID_ARM_NEON=<span class="keyword">TRUE</span> \</span><br><span class="line">-DENABLE_NEON=<span class="keyword">ON</span> \</span><br><span class="line">-DBUILD_PNG=<span class="keyword">ON</span> \</span><br><span class="line">-DBUILD_JASPER=<span class="keyword">ON</span> \</span><br><span class="line">-DBUILD_JPEG=<span class="keyword">ON</span> \</span><br><span class="line">-DBUILD_TIFF=<span class="keyword">ON</span> \</span><br><span class="line">-DBUILD_ZLIB=<span class="keyword">ON</span> \</span><br><span class="line">-DWITH_JPEG=<span class="keyword">ON</span> \</span><br><span class="line">-DWITH_PNG=<span class="keyword">ON</span> \</span><br><span class="line">-DWITH_JASPER=<span class="keyword">ON</span> \</span><br><span class="line">-DWITH_TIFF=<span class="keyword">ON</span> \</span><br><span class="line">-DSOFTFP=<span class="keyword">ON</span> \</span><br><span class="line">-DBUILD_JAVA=<span class="keyword">OFF</span> \</span><br><span class="line">-DBUILD_ANDROID_EXAMPLES=<span class="keyword">OFF</span> \</span><br><span class="line">-DBUILD_ANDROID_PROJECTS=<span class="keyword">OFF</span> \</span><br><span class="line">-DANDROID_STL=c++_shared \</span><br><span class="line">-DANDROID_ABI=armeabi-v7a \</span><br><span class="line">-DBUILD_SHARED_LIBS=<span class="keyword">ON</span> \</span><br><span class="line">-DCMAKE_INSTALL_PREFIX=opencv/<span class="keyword">install</span> \</span><br><span class="line">..</span><br></pre></td></tr></table></figure></li><li><p>编译</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ make -j24 && make install</span><br></pre></td></tr></table></figure></li><li><p>检查生成文件</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> opencv/install/sdk</span><br><span class="line"><span class="comment"># etc 目录,存放了人脸识别模块部分资源文件,licenses等</span></span><br><span class="line">vectoros@vectoros:~/opencv/install/sdk$ ll etc/</span><br><span class="line">total 28</span><br><span class="line">drwxrwxr-x 5 vectoros vectoros 4096 Oct 8 10:50 ./</span><br><span class="line">drwxrwxr-x 4 vectoros vectoros 4096 Oct 8 10:50 ../</span><br><span class="line">drwxrwxr-x 2 vectoros vectoros 4096 Oct 8 10:50 haarcascades/</span><br><span class="line">drwxrwxr-x 2 vectoros vectoros 4096 Oct 8 10:50 lbpcascades/</span><br><span class="line">drwxrwxr-x 2 vectoros vectoros 4096 Oct 8 10:50 licenses/</span><br><span class="line">-rw-r--r-- 1 vectoros vectoros 2593 Aug 24 23:19 valgrind_3rdparty.supp</span><br><span class="line">-rw-r--r-- 1 vectoros vectoros 4088 Aug 24 23:19 valgrind.supp</span><br><span class="line"></span><br><span class="line"><span class="comment"># native/jni/include 目录,存放了对应的.h .hpp头文件</span></span><br><span class="line">vectoros@vectoros:~/opencv/install/sdk/native$ ll jni/include/</span><br><span class="line">drwxrwxr-x 16 vectoros vectoros 4096 Oct 8 10:50 opencv2/</span><br><span class="line"></span><br><span class="line"><span class="comment"># native/libs/armeabi-v7a/ 目录,存放了jni的so库或者.a文件</span></span><br><span class="line">vectoros@vectoros:~/opencv/install/sdk/native$ ll libs/armeabi-v7a/*.so</span><br><span class="line">-rw-r--r-- 1 vectoros vectoros 13462060 Oct 8 10:48 libs/armeabi-v7a/libopencv_calib3d.so</span><br><span class="line">-rw-r--r-- 1 vectoros vectoros 25141056 Oct 8 10:46 libs/armeabi-v7a/libopencv_core.so</span><br><span class="line">-rw-r--r-- 1 vectoros vectoros 50133564 Oct 8 10:47 libs/armeabi-v7a/libopencv_dnn.so</span><br><span class="line">-rw-r--r-- 1 vectoros vectoros 6983552 Oct 8 10:47 libs/armeabi-v7a/libopencv_features2d.so</span><br><span class="line">-rw-r--r-- 1 vectoros vectoros 3502996 Oct 8 10:46 libs/armeabi-v7a/libopencv_flann.so</span><br><span class="line">-rw-r--r-- 1 vectoros vectoros 525868 Oct 8 10:47 libs/armeabi-v7a/libopencv_highgui.so</span><br><span class="line">-rw-r--r-- 1 vectoros vectoros 21684136 Oct 8 10:47 libs/armeabi-v7a/libopencv_imgcodecs.so</span><br><span class="line">-rw-r--r-- 1 vectoros vectoros 26117996 Oct 8 10:46 libs/armeabi-v7a/libopencv_imgproc.so</span><br><span class="line">-rw-r--r-- 1 vectoros vectoros 6184124 Oct 8 10:46 libs/armeabi-v7a/libopencv_ml.so</span><br><span class="line">-rw-r--r-- 1 vectoros vectoros 3730776 Oct 8 10:49 libs/armeabi-v7a/libopencv_objdetect.so</span><br><span class="line">-rw-r--r-- 1 vectoros vectoros 5078460 Oct 8 10:47 libs/armeabi-v7a/libopencv_photo.so</span><br><span class="line">-rw-r--r-- 1 vectoros vectoros 7637264 Oct 8 10:49 libs/armeabi-v7a/libopencv_stitching.so</span><br><span class="line">-rw-r--r-- 1 vectoros vectoros 3361504 Oct 8 10:47 libs/armeabi-v7a/libopencv_videoio.so</span><br><span class="line">-rw-r--r-- 1 vectoros vectoros 3026088 Oct 8 10:49 libs/armeabi-v7a/libopencv_video.so</span><br></pre></td></tr></table></figure></li><li><p>讲生成的文件应用到AndroidStudio NDK Projects里面</p></li></ol><h2 id="编译配置解析"><a href="#编译配置解析" class="headerlink" title="编译配置解析"></a>编译配置解析</h2><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">-DCMAKE_TOOLCHAIN_FILE=/opt/ndk/build/cmake/android.toolchain.cmake <span class="comment"># 指定编译工具链cmake脚本</span></span><br><span class="line">-DANDROID_NDK=/opt/ndk <span class="comment"># 指定NDK路径</span></span><br><span class="line">-DANDROID_NATIVE_API_LEVEL=android-<span class="number">21</span> <span class="comment"># 指定NDK API Level</span></span><br><span class="line">-DCMAKE_BUILD_TYPE=Release <span class="comment"># 指定编译类型,默认是Debug类型,Release会有性能上的提升</span></span><br><span class="line">-DENABLE_VFPV3=<span class="keyword">ON</span> <span class="comment"># 开启VFP优化选项</span></span><br><span class="line">-DANDROID_ARM_NEON=<span class="keyword">TRUE</span> <span class="comment"># 设置NDK支持NEON</span></span><br><span class="line">-DENABLE_NEON=<span class="keyword">ON</span> <span class="comment"># 开启O彭CV NEON优化选项</span></span><br><span class="line">-DBUILD_PNG=<span class="keyword">ON</span> <span class="comment"># 编译PNG模块</span></span><br><span class="line">-DBUILD_JASPER=<span class="keyword">ON</span> <span class="comment"># 编译JASPER模块</span></span><br><span class="line">-DBUILD_JPEG=<span class="keyword">ON</span> <span class="comment"># 编译JPEG模块</span></span><br><span class="line">-DBUILD_TIFF=<span class="keyword">ON</span> <span class="comment"># 编译TIFF模块</span></span><br><span class="line">-DBUILD_ZLIB=<span class="keyword">ON</span> <span class="comment"># 编译ZLIB模块</span></span><br><span class="line">-DWITH_JPEG=<span class="keyword">ON</span> <span class="comment"># 生成JPEG模块</span></span><br><span class="line">-DWITH_PNG=<span class="keyword">ON</span> <span class="comment"># 生成PNG模块</span></span><br><span class="line">-DWITH_JASPER=<span class="keyword">ON</span> <span class="comment"># 生成JASPER模块</span></span><br><span class="line">-DWITH_TIFF=<span class="keyword">ON</span> <span class="comment"># 生成TIFF模块</span></span><br><span class="line">-DSOFTFP=<span class="keyword">ON</span> <span class="comment"># 开启SOFTFP</span></span><br><span class="line">-DBUILD_JAVA=<span class="keyword">OFF</span> <span class="comment"># 编译Java,这里只需要C++版本,如果需要java,设置为ON</span></span><br><span class="line">-DBUILD_ANDROID_EXAMPLES=<span class="keyword">OFF</span> <span class="comment"># 编译Android Examples</span></span><br><span class="line">-DBUILD_ANDROID_PROJECTS=<span class="keyword">OFF</span> <span class="comment"># 编译Android Projects</span></span><br><span class="line">-DANDROID_STL=c++_shared <span class="comment"># 指定STL版本,新版NDK里面默认使用c++_shared</span></span><br><span class="line">-DANDROID_ABI=armeabi-v7a <span class="comment"># 指定生成ABI版本</span></span><br><span class="line">-DBUILD_SHARED_LIBS=<span class="keyword">ON</span> <span class="comment"># 是否生成共享so库,如果不设置,默认生成.a静态库</span></span><br><span class="line">-DCMAKE_INSTALL_PREFIX=opencv/<span class="keyword">install</span> <span class="comment"># 安装路径,用于生成需要的头文件和so或者.a静态库(可选)</span></span><br><span class="line">.. <span class="comment"># 指定OpenCV代码根目录(重要)</span></span><br></pre></td></tr></table></figure><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ol><li><a target="_blank" rel="noopener" href="https://www.learnopencv.com/install-opencv-on-android-tiny-and-optimized/">https://www.learnopencv.com/install-opencv-on-android-tiny-and-optimized/</a></li><li><a target="_blank" rel="noopener" href="https://www.sisik.eu/blog/android/ndk/opencv-without-java">https://www.sisik.eu/blog/android/ndk/opencv-without-java</a></li></ol></div><footer class="post-footer"><div class="post-eof"></div></footer></article></div><div class="post-block"><article itemscope itemtype="http://schema.org/Article" class="post-content"><link itemprop="mainEntityOfPage" href="http://www.vectoros.club/post/dd932aba.html"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="image" content="/uploads/avatar.webp"><meta itemprop="name" content="Vectoros"><meta itemprop="description" content=""></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="Keep Learning"></span><header class="post-header"><h2 class="post-title" itemprop="name headline"><a href="/post/dd932aba.html" class="post-title-link" itemprop="url">AndroidStudio OpenCV NDK tutorial</a></h2><div class="post-meta-container"><div class="post-meta"><span class="post-meta-item"><span class="post-meta-item-icon"><i class="far fa-calendar"></i> </span><span class="post-meta-item-text">发表于</span> <time title="创建时间:2019-07-02 21:47:09" itemprop="dateCreated datePublished" datetime="2019-07-02T21:47:09+08:00">2019-07-02</time> </span><span class="post-meta-item"><span class="post-meta-item-icon"><i class="far fa-folder"></i> </span><span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/" itemprop="url" rel="index"><span itemprop="name">Android</span></a> </span>, <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/NDK/" itemprop="url" rel="index"><span itemprop="name">NDK</span></a> </span>, <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/NDK/OpenCV/" itemprop="url" rel="index"><span itemprop="name">OpenCV</span></a></span></span></div></div></header><div class="post-body" itemprop="articleBody"><h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><ul><li>OpenCV是目前计算机视觉里面非常常用的一个开源库,支持各大平台</li></ul><h2 id="准备条件"><a href="#准备条件" class="headerlink" title="准备条件"></a>准备条件</h2><ul><li>AndroidStudio 最新版本</li><li>SDK Manager里面安装SDK, NDK</li><li>OpenCV 3.4/4.0<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wget https://codeload.github.com/OpenCV/OpenCV/zip/3.4.6</span><br></pre></td></tr></table></figure></li></ul><h2 id="准备知识-CMake"><a href="#准备知识-CMake" class="headerlink" title="准备知识-CMake"></a>准备知识-CMake</h2><p>AndroidStudio 支持cmake编译C/C++文件,通过编写CMakeList.txt来实现</p><h3 id="常用变量"><a href="#常用变量" class="headerlink" title="常用变量"></a>常用变量</h3><figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">${CMAKE_SOURCE_DIR} <span class="comment"># CMakeLists.txt文件所在位置</span></span><br><span class="line">${ANDROID_ABI} <span class="comment"># Android ABI架构 ("armeabi-v7a","arm64-v8a")</span></span><br></pre></td></tr></table></figure><h3 id="常用函数"><a href="#常用函数" class="headerlink" title="常用函数"></a>常用函数</h3><ul><li><p>常用指令</p><figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Set project</span></span><br><span class="line">project(demo)</span><br><span class="line"><span class="comment"># Set variable</span></span><br><span class="line">set(VARIABLE, VALUE)</span><br><span class="line"><span class="comment"># Show message</span></span><br><span class="line">message(${ANDROID_ABI})</span><br><span class="line"><span class="comment"># if else</span></span><br><span class="line">if(${ANDROID_ABI} STREQUAL <span class="string">"areambi"</span>)</span><br><span class="line"> message(<span class="string">"armv5"</span>)</span><br><span class="line">elseif(${ANDROID_ABI} STREQUAL <span class="string">"areambi-v7a"</span>)</span><br><span class="line"> message(<span class="string">"armv7a"</span>)</span><br><span class="line">elseif(${ANDROID_ABI} STREQUAL <span class="string">"arm64-v8a"</span>)</span><br><span class="line"> message(<span class="string">"armv8a"</span>)</span><br><span class="line">elseif(${ANDROID_ABI} STREQUAL <span class="string">"x86_64"</span>)</span><br><span class="line"> message(<span class="string">"x86_64"</span>)</span><br><span class="line">elseif(${ANDROID_ABI} STREQUAL <span class="string">"x86"</span>)</span><br><span class="line"> message(<span class="string">"x86"</span>)</span><br><span class="line"><span class="keyword">else</span>()</span><br><span class="line"> message(<span class="string">"unknown abi"</span>)</span><br><span class="line"><span class="keyword">endif</span>()</span><br></pre></td></tr></table></figure></li><li><p>添加共享库</p><figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">add_library( </span><br><span class="line"><span class="comment"># Sets the name of the library.</span></span><br><span class="line">native-lib</span><br><span class="line"><span class="comment"># Sets the library as a shared library.</span></span><br><span class="line">SHARED</span><br><span class="line"><span class="comment"># Provides a relative path to your source file(s).</span></span><br><span class="line">src/main/cpp/native-lib.cpp)</span><br></pre></td></tr></table></figure></li><li><p>添加可执行文件</p><figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">add_executable( </span><br><span class="line"><span class="comment"># Sets the name of the executable file.</span></span><br><span class="line">test</span><br><span class="line"><span class="comment"># Provides a relative path to your source file(s).</span></span><br><span class="line">src/main/cpp/main.cpp)</span><br></pre></td></tr></table></figure></li><li><p>查找NDK library</p><figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Searches for a specified prebuilt library and stores the path as a</span></span><br><span class="line"><span class="comment"># variable. Because CMake includes system libraries in the search path by</span></span><br><span class="line"><span class="comment"># default, you only need to specify the name of the public NDK library</span></span><br><span class="line"><span class="comment"># you want to add. CMake verifies that the library exists before</span></span><br><span class="line"><span class="comment"># completing its build.</span></span><br><span class="line"></span><br><span class="line">find_library( <span class="comment"># Sets the name of the path variable.</span></span><br><span class="line"> log-lib</span><br><span class="line"></span><br><span class="line"> <span class="comment"># Specifies the name of the NDK library that</span></span><br><span class="line"> <span class="comment"># you want CMake to locate.</span></span><br><span class="line"> log)</span><br></pre></td></tr></table></figure></li><li><p>指定链接库</p><figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Specifies libraries CMake should link to your target library. You</span></span><br><span class="line"><span class="comment"># can link multiple libraries, such as libraries you define in this</span></span><br><span class="line"><span class="comment"># build script, prebuilt third-party libraries, or system libraries.</span></span><br><span class="line"></span><br><span class="line">target_link_libraries( <span class="comment"># Specifies the target library.</span></span><br><span class="line"> test</span><br><span class="line"> <span class="comment"># Links the target library to the log library</span></span><br><span class="line"> <span class="comment"># included in the NDK.</span></span><br><span class="line"> ${log-lib})</span><br></pre></td></tr></table></figure></li><li><p>指定包含头文件</p><figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/<span class="keyword">include</span>/)</span><br><span class="line">include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/OpenCV)</span><br></pre></td></tr></table></figure></li><li><p>手动指定共享库</p><figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">add_library(libOpenCV_java3 SHARED IMPORTED)</span><br><span class="line">set_target_properties(libOpenCV_java3 PROPERTIES IMPORTED_LOCATION</span><br><span class="line"> ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libOpenCV_java3.so)</span><br></pre></td></tr></table></figure></li><li><p>查找所有源文件,并保存到<code>IR_SRCS</code>变量,但是不能查找子目录</p><figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">aux_source_directory(${CMAKE_SOURCE_DIR}/src/main/cpp DIR_SRCS)</span><br></pre></td></tr></table></figure></li></ul><h3 id="编译器设置"><a href="#编译器设置" class="headerlink" title="编译器设置"></a>编译器设置</h3><p>我们可以在CMakeLists.txt里面设置编译器参数,也可以在build.gradle脚本里面设置</p><ul><li><p>CMakeLists.txt 设置</p><figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#支持-std=gnu++11</span></span><br><span class="line">set(CMAKE_VERBOSE_MAKEFILE on)</span><br><span class="line">set(CMAKE_CXX_FLAGS <span class="string">"${CMAKE_CXX_FLAGS} -std=gnu++11"</span>)</span><br></pre></td></tr></table></figure></li><li><p>build.gradle 脚本设置</p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">apply plugin: <span class="string">'com.android.application'</span></span><br><span class="line"></span><br><span class="line">android {</span><br><span class="line"> defaultConfig {</span><br><span class="line"> externalNativeBuild {</span><br><span class="line"> cmake {</span><br><span class="line"> <span class="comment">//设置cpp Flags</span></span><br><span class="line"> cppFlags <span class="string">"-std=c++11 -frtti -fexceptions"</span></span><br><span class="line"> <span class="comment">//设置STL共享库,这里要注意,部分Android系统里面可能没有libc++_shared.so,这个时候需要在app里面打包进去</span></span><br><span class="line"> <span class="comment">//文件路径在NDK安装目录下 sources/cxx-stl/llvm-libc++/libs/${ANDROID_ABI}/libc++_shared.so</span></span><br><span class="line"> arguments <span class="string">"-DANDROID_STL=c++_shared"</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul><h3 id="输出设置"><a href="#输出设置" class="headerlink" title="输出设置"></a>输出设置</h3><ul><li><p>动态共享库 <code>.so</code></p><figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/OpenCV)</span><br><span class="line">include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/<span class="keyword">include</span>/)</span><br><span class="line">add_library(libOpenCV_java3 SHARED IMPORTED)</span><br><span class="line">set_target_properties(libOpenCV_java3 PROPERTIES IMPORTED_LOCATION</span><br><span class="line"> ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libOpenCV_java3.so)</span><br><span class="line">find_library( <span class="comment"># Sets the name of the path variable.</span></span><br><span class="line"> log-lib</span><br><span class="line"></span><br><span class="line"> <span class="comment"># Specifies the name of the NDK library that</span></span><br><span class="line"> <span class="comment"># you want CMake to locate.</span></span><br><span class="line"> log)</span><br><span class="line">add_library( <span class="comment"># Sets the name of the library.</span></span><br><span class="line"> native-lib</span><br><span class="line"></span><br><span class="line"> <span class="comment"># Sets the library as a shared library.</span></span><br><span class="line"> SHARED</span><br><span class="line"></span><br><span class="line"> <span class="comment"># Provides a relative path to your source file(s).</span></span><br><span class="line"></span><br><span class="line"> src/main/cpp/native-lib.cpp)</span><br><span class="line">target_link_libraries( <span class="comment"># Specifies the target library.</span></span><br><span class="line"> native-lib</span><br><span class="line"> libOpenCV_java3</span><br><span class="line"> <span class="comment"># Links the target library to the log library</span></span><br><span class="line"> <span class="comment"># included in the NDK.</span></span><br><span class="line"> ${log-lib})</span><br></pre></td></tr></table></figure></li><li><p>静态共享库 <code>.a</code></p><figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/OpenCV)</span><br><span class="line">include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/<span class="keyword">include</span>/)</span><br><span class="line">add_library(libOpenCV_java3 SHARED IMPORTED)</span><br><span class="line">set_target_properties(libOpenCV_java3 PROPERTIES IMPORTED_LOCATION</span><br><span class="line"> ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libOpenCV_java3.so)</span><br><span class="line">find_library( <span class="comment"># Sets the name of the path variable.</span></span><br><span class="line"> log-lib</span><br><span class="line"></span><br><span class="line"> <span class="comment"># Specifies the name of the NDK library that</span></span><br><span class="line"> <span class="comment"># you want CMake to locate.</span></span><br><span class="line"> log)</span><br><span class="line">add_library( <span class="comment"># Sets the name of the library.</span></span><br><span class="line"> native-lib</span><br><span class="line"></span><br><span class="line"> <span class="comment"># Sets the library as a static library.</span></span><br><span class="line"> STATIC</span><br><span class="line"></span><br><span class="line"> <span class="comment"># Provides a relative path to your source file(s).</span></span><br><span class="line"></span><br><span class="line"> src/main/cpp/native-lib.cpp)</span><br><span class="line">target_link_libraries( <span class="comment"># Specifies the target library.</span></span><br><span class="line"> native-lib</span><br><span class="line"> libOpenCV_java3</span><br><span class="line"> <span class="comment"># Links the target library to the log library</span></span><br><span class="line"> <span class="comment"># included in the NDK.</span></span><br><span class="line"> ${log-lib})</span><br></pre></td></tr></table></figure></li><li><p>Executable</p><figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/OpenCV)</span><br><span class="line">include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/<span class="keyword">include</span>/)</span><br><span class="line">add_library(libOpenCV_java3 SHARED IMPORTED)</span><br><span class="line">set_target_properties(libOpenCV_java3 PROPERTIES IMPORTED_LOCATION</span><br><span class="line"> ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libOpenCV_java3.so)</span><br><span class="line">find_library( <span class="comment"># Sets the name of the path variable.</span></span><br><span class="line"> log-lib</span><br><span class="line"></span><br><span class="line"> <span class="comment"># Specifies the name of the NDK library that</span></span><br><span class="line"> <span class="comment"># you want CMake to locate.</span></span><br><span class="line"> log)</span><br><span class="line"><span class="comment"># 设置可执行文件的输出目录</span></span><br><span class="line">set(EXECUTABLE_OUTPUT_PATH <span class="string">"${CMAKE_SOURCE_DIR}/src/main/assets/${ANDROID_ABI}"</span>)</span><br><span class="line"><span class="comment"># 添加可执行文件的源文件</span></span><br><span class="line">add_executable(</span><br><span class="line"> test</span><br><span class="line"></span><br><span class="line"> src/main/cpp/main.cpp</span><br><span class="line">)</span><br><span class="line">target_link_libraries( <span class="comment"># Specifies the target library.</span></span><br><span class="line"> test</span><br><span class="line"> libOpenCV_java3</span><br><span class="line"> <span class="comment"># Links the target library to the log library</span></span><br><span class="line"> <span class="comment"># included in the NDK.</span></span><br><span class="line"> ${log-lib})</span><br></pre></td></tr></table></figure></li></ul><h3 id="依赖设置"><a href="#依赖设置" class="headerlink" title="依赖设置"></a>依赖设置</h3><h3 id="与Gradle结合"><a href="#与Gradle结合" class="headerlink" title="与Gradle结合"></a>与Gradle结合</h3><h2 id="新建Project"><a href="#新建Project" class="headerlink" title="新建Project"></a>新建Project</h2><p>用AndroidStudio创建项目,并选择Native C++支持</p><h2 id="导入OpenCV头文件"><a href="#导入OpenCV头文件" class="headerlink" title="导入OpenCV头文件"></a>导入OpenCV头文件</h2><ol><li>在<code>src/main/cpp</code>目录下创建<code>include</code>目录</li><li>将OpenCV SDK解压后,<code>sdk/native/jni/include/</code>目录下的两个头文件文件夹<code>OpenCV, OpenCV2</code>复制到上面创建的<code>include</code>目录下</li><li>CMakeList.txt添加对应引用<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include/)</span><br></pre></td></tr></table></figure></li></ol><h2 id="导入OpenCV-so库"><a href="#导入OpenCV-so库" class="headerlink" title="导入OpenCV so库"></a>导入OpenCV so库</h2><ol><li>创建<code>src/main/jniLibs</code>目录,用于存放第三方共享库</li><li>将OpenCV SDK解压后,<code>sdk/native/libs/</code>目录下的<code>so</code>文件文件夹复制到上面创建的<code>jniLibs</code>目录下,这些文件夹是以<code>abi</code>为目录保存的。</li><li>CMakeList.txt添加对应依赖<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">add_library(libOpenCV_java3 SHARED IMPORTED)</span><br><span class="line">set_target_properties(libOpenCV_java3 PROPERTIES IMPORTED_LOCATION</span><br><span class="line"> ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libOpenCV_java3.so)</span><br></pre></td></tr></table></figure></li></ol><h2 id="jni引用OpenCV方法"><a href="#jni引用OpenCV方法" class="headerlink" title="jni引用OpenCV方法"></a>jni引用OpenCV方法</h2><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"OpenCV2/core.hpp"</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> cv;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="编译验证"><a href="#编译验证" class="headerlink" title="编译验证"></a>编译验证</h2></div><footer class="post-footer"><div class="post-eof"></div></footer></article></div><div class="post-block"><article itemscope itemtype="http://schema.org/Article" class="post-content"><link itemprop="mainEntityOfPage" href="http://www.vectoros.club/post/1b1cf1e2.html"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="image" content="/uploads/avatar.webp"><meta itemprop="name" content="Vectoros"><meta itemprop="description" content=""></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="Keep Learning"></span><header class="post-header"><h2 class="post-title" itemprop="name headline"><a href="/post/1b1cf1e2.html" class="post-title-link" itemprop="url">Build Tensorflow Lite benchmark for Android</a></h2><div class="post-meta-container"><div class="post-meta"><span class="post-meta-item"><span class="post-meta-item-icon"><i class="far fa-calendar"></i> </span><span class="post-meta-item-text">发表于</span> <time title="创建时间:2019-06-15 16:42:50" itemprop="dateCreated datePublished" datetime="2019-06-15T16:42:50+08:00">2019-06-15</time> </span><span class="post-meta-item"><span class="post-meta-item-icon"><i class="far fa-folder"></i> </span><span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/" itemprop="url" rel="index"><span itemprop="name">Android</span></a> </span>, <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/Tensorflow/" itemprop="url" rel="index"><span itemprop="name">Tensorflow</span></a> </span>, <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/Tensorflow/TFLite/" itemprop="url" rel="index"><span itemprop="name">TFLite</span></a> </span>, <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Android/Tensorflow/TFLite/Benchmark/" itemprop="url" rel="index"><span itemprop="name">Benchmark</span></a></span></span></div></div></header><div class="post-body" itemprop="articleBody"><p>我们在部署模型到Android端的时候,需要先评估模型的性能,Tensorflow官方给我们提供了TFLite的benchmark工具</p><h1 id="整体流程"><a href="#整体流程" class="headerlink" title="整体流程"></a>整体流程</h1><ol><li>准备编译环境</li><li>安装依赖项目</li><li>安装编译工具</li><li>下载tensorflow源码</li><li>编译benchmark</li><li>部署到Android设备上</li><li>运行</li></ol><h2 id="准备编译环境"><a href="#准备编译环境" class="headerlink" title="准备编译环境"></a>准备编译环境</h2><p>建议用Linux系统,这个部分可以参考<a target="_blank" rel="noopener" href="https://www.tensorflow.org/install/source">官方指南</a>, 我这边使用的Ubuntu 18.04</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># install python and prerequisites</span></span><br><span class="line">sudo apt install python-dev python-pip</span><br><span class="line">pip install -U --user pip six numpy wheel mock</span><br><span class="line">pip install -U --user keras_applications==1.0.6 --no-deps</span><br><span class="line">pip install -U --user keras_preprocessing==1.0.5 --no-deps</span><br><span class="line"></span><br><span class="line"><span class="comment"># install openjdk-8</span></span><br><span class="line">sudo apt-get install openjdk-8-jdk</span><br></pre></td></tr></table></figure><h2 id="安装编译工具bazel"><a href="#安装编译工具bazel" class="headerlink" title="安装编译工具bazel"></a>安装编译工具<code>bazel</code></h2><p>参考<a target="_blank" rel="noopener" href="https://docs.bazel.build/versions/master/install.html">bazel官网</a>,编译最新版本需要bazel版本>=0.24.1</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># install the prerequisites</span></span><br><span class="line">sudo apt-get install pkg-config zip g++ zlib1g-dev unzip python</span><br><span class="line"></span><br><span class="line"><span class="comment"># download bazel from github</span></span><br><span class="line"><span class="comment"># Next, download the Bazel binary installer named bazel-<version>-installer-linux-x86_64.sh from the Bazel releases page on GitHub.</span></span><br><span class="line">wget https://github.com/bazelbuild/bazel/releases/download/0.24.1/bazel-0.24.1-installer-linux-x86_64.sh</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># run the installer 0.24.1</span></span><br><span class="line">chmod +x bazel-0.24.1-installer-linux-x86_64.sh</span><br><span class="line">./bazel-0.24.1-installer-linux-x86_64.sh --user</span><br><span class="line"></span><br><span class="line"><span class="comment"># setup environment</span></span><br><span class="line"><span class="built_in">export</span> PATH=<span class="string">"<span class="variable">$PATH</span>:<span class="variable">$HOME</span>/bin"</span></span><br></pre></td></tr></table></figure><h2 id="安装Android-SDK和NDK"><a href="#安装Android-SDK和NDK" class="headerlink" title="安装Android SDK和NDK"></a>安装Android SDK和NDK</h2><p>编译Android平台的benchmark需要Android SDK和NDK(里面包含Build tools, Platform tools)</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">mkdir ~/Android</span><br><span class="line"><span class="built_in">cd</span> Android</span><br><span class="line"><span class="comment"># NDK</span></span><br><span class="line">wget https://dl.google.com/android/repository/android-ndk-r17c-linux-x86_64.zip</span><br><span class="line">unzip android-ndk-r17c-linux-x86_64.zip</span><br><span class="line">mkdir Sdk</span><br><span class="line">mv android-ndk-r17c Sdk/ndk-bundle</span><br><span class="line"></span><br><span class="line"><span class="comment"># SDK tools</span></span><br><span class="line">wget https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip</span><br><span class="line">unzip sdk-tools-linux-4333796.zip </span><br><span class="line">mv tools/ Sdk/</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># Platform tools</span></span><br><span class="line">wget https://dl.google.com/android/repository/platform-tools-latest-linux.zip</span><br><span class="line">unzip platform-tools-latest-linux.zip </span><br><span class="line">mv platform-tools Sdk/</span><br><span class="line"></span><br><span class="line"><span class="comment"># Using sdkmanager to install tools</span></span><br><span class="line"><span class="built_in">cd</span> Sdk</span><br><span class="line">chmod a+x tools/bin/sdkmanager</span><br><span class="line">./tools/bin/sdkmanager <span class="string">"platform-tools"</span> <span class="string">"platforms;android-28"</span> <span class="string">"platforms;android-29"</span> <span class="string">"build-tools;29.0.0"</span> </span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="编译tflite-benchmark"><a href="#编译tflite-benchmark" class="headerlink" title="编译tflite benchmark"></a>编译tflite benchmark</h2><p>参考<a target="_blank" rel="noopener" href="https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite/tools/benchmark">官方文档</a></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># download tensorflow code</span></span><br><span class="line">git <span class="built_in">clone</span> https://github.com/tensorflow/tensorflow.git</span><br><span class="line"></span><br><span class="line"><span class="comment"># build benchmark for android</span></span><br><span class="line">bazel build -c opt \</span><br><span class="line"> --config=android_arm \</span><br><span class="line"> --cxxopt=<span class="string">'--std=c++11'</span> \</span><br><span class="line"> tensorflow/lite/tools/benchmark:benchmark_model</span><br><span class="line"></span><br><span class="line"><span class="comment"># build benchmark for desktop</span></span><br><span class="line">bazel build -c opt --cxxopt=<span class="string">'--std=c++11'</span> tensorflow/lite/tools/benchmark:benchmark_model</span><br></pre></td></tr></table></figure><h2 id="在Android上运行"><a href="#在Android上运行" class="headerlink" title="在Android上运行"></a>在Android上运行</h2><p>编译好的benchmark_model是一个Android平台的可运行的二进制文件,可以在adb shell里面直接运行</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">adb push bazel-bin/tensorflow/lite/tools/benchmark/benchmark_model /data/<span class="built_in">local</span>/tmp</span><br><span class="line"></span><br><span class="line">adb shell chmod +x /data/<span class="built_in">local</span>/tmp/benchmark_model</span><br><span class="line"></span><br><span class="line">adb push mobilenet_v2_1.0_224_quant.tflite /data/<span class="built_in">local</span>/tmp</span><br><span class="line"></span><br><span class="line">/data/<span class="built_in">local</span>/tmp/benchmark_model \</span><br><span class="line"> --graph=/data/<span class="built_in">local</span>/tmp/mobilenet_v2_1.0_224_quant.tflite \</span><br><span class="line"> --num_threads=10</span><br><span class="line"></span><br><span class="line"><span class="comment"># tashset f0 是 Pixel系列手机上,让程序运行在Big core上的命令</span></span><br><span class="line">adb shell taskset f0 /data/<span class="built_in">local</span>/tmp/benchmark_model \</span><br><span class="line"> --graph=/data/<span class="built_in">local</span>/tmp/mobilenet_v2_1.0_224_quant.tflite \</span><br><span class="line"> --enable_op_profiling=<span class="literal">true</span></span><br></pre></td></tr></table></figure><h2 id="运行结果"><a href="#运行结果" class="headerlink" title="运行结果"></a>运行结果</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># mobilenet</span></span><br><span class="line">taskset f0 /data/<span class="built_in">local</span>/tmp/benchmark_model \</span><br><span class="line"> --graph=/data/<span class="built_in">local</span>/tmp/mobilenet_v2_1.0_224_quant.tflite \</span><br><span class="line"> --enable_op_profiling=<span class="literal">true</span></span><br><span class="line"></span><br><span class="line">STARTING!</span><br><span class="line">Min num runs: [50]</span><br><span class="line">Min runs duration (seconds): [1]</span><br><span class="line">Inter-run delay (seconds): [-1]</span><br><span class="line">Num threads: [1]</span><br><span class="line">Benchmark name: []</span><br><span class="line">Output prefix: []</span><br><span class="line">Min warmup runs: [1]</span><br><span class="line">Min warmup runs duration (seconds): [0.5]</span><br><span class="line">Graph: [/data/<span class="built_in">local</span>/tmp/mobilenet_v2_1.0_224_quant.tflite]</span><br><span class="line">Input layers: []</span><br><span class="line">Input shapes: []</span><br><span class="line">Use nnapi : [0]</span><br><span class="line">Use legacy nnapi : [0]</span><br><span class="line">Use gpu : [0]</span><br><span class="line">Allow fp16 : [0]</span><br><span class="line">Enable op profiling: [1]</span><br><span class="line">Loaded model /data/<span class="built_in">local</span>/tmp/mobilenet_v2_1.0_224_quant.tflite</span><br><span class="line">resolved reporter</span><br><span class="line">INFO: Initialized TensorFlow Lite runtime.</span><br><span class="line">Initialized session <span class="keyword">in</span> 1.892ms</span><br><span class="line">Running benchmark <span class="keyword">for</span> at least 1 iterations and at least 0.5 seconds</span><br><span class="line">count=6 first=91810 curr=85097 min=84834 max=91810 avg=86184.3 std=2519</span><br><span class="line"></span><br><span class="line">Running benchmark <span class="keyword">for</span> at least 50 iterations and at least 1 seconds</span><br><span class="line">count=50 first=118810 curr=114219 min=88216 max=129193 avg=115062 std=7678</span><br><span class="line"></span><br><span class="line">Average inference timings <span class="keyword">in</span> us: Warmup: 86184.3, Init: 1892, no stats: 115062</span><br><span class="line">============================== Run Order ==============================</span><br><span class="line"> [node <span class="built_in">type</span>] [start] [first] [avg ms] [%] [cdf%] [mem KB] [<span class="built_in">times</span> called] [Name]</span><br><span class="line"> CONV_2D 0.000 5.567 7.237 6.297% 6.297% 0.000 1 [MobilenetV2/Conv/Relu6]</span><br><span class="line"> DEPTHWISE_CONV_2D 7.241 3.518 3.726 3.243% 9.539% 0.000 1 [MobilenetV2/expanded_conv/depthwise/Relu6]</span><br><span class="line"> CONV_2D 10.971 2.399 3.711 3.229% 12.768% 0.000 1 [MobilenetV2/expanded_conv/project/add_fold]</span><br><span class="line"> CONV_2D 14.688 12.247 17.846 15.529% 28.297% 0.000 1 [MobilenetV2/expanded_conv_1/expand/Relu6]</span><br><span class="line"> DEPTHWISE_CONV_2D 32.539 2.594 3.486 3.033% 31.330% 0.000 1 [MobilenetV2/expanded_conv_1/depthwise/Relu6]</span><br><span class="line"> CONV_2D 36.028 1.460 2.462 2.142% 33.472% 0.000 1 [MobilenetV2/expanded_conv_1/project/add_fold]</span><br><span class="line"> CONV_2D 38.493 12.619 7.820 6.805% 40.277% 0.000 1 [MobilenetV2/expanded_conv_2/expand/Relu6]</span><br><span class="line"> DEPTHWISE_CONV_2D 46.318 4.750 3.683 3.205% 43.482% 0.000 1 [MobilenetV2/expanded_conv_2/depthwise/Relu6]</span><br><span class="line"> CONV_2D 50.005 4.853 3.305 2.876% 46.358% 0.000 1 [MobilenetV2/expanded_conv_2/project/add_fold]</span><br><span class="line"> ADD 53.313 0.279 0.293 0.255% 46.613% 0.000 1 [MobilenetV2/expanded_conv_2/add]</span><br><span class="line"> CONV_2D 53.607 12.993 7.827 6.811% 53.424% 0.000 1 [MobilenetV2/expanded_conv_3/expand/Relu6]</span><br><span class="line"> DEPTHWISE_CONV_2D 61.438 2.546 1.647 1.434% 54.857% 0.000 1 [MobilenetV2/expanded_conv_3/depthwise/Relu6]</span><br><span class="line"> CONV_2D 63.089 1.239 1.009 0.878% 55.735% 0.000 1 [MobilenetV2/expanded_conv_3/project/add_fold]</span><br><span class="line"> CONV_2D 64.099 2.261 2.151 1.872% 57.607% 0.000 1 [MobilenetV2/expanded_conv_4/expand/Relu6]</span><br><span class="line"> DEPTHWISE_CONV_2D 66.253 1.251 1.238 1.077% 58.685% 0.000 1 [MobilenetV2/expanded_conv_4/depthwise/Relu6]</span><br><span class="line"> CONV_2D 67.493 1.074 1.126 0.980% 59.665% 0.000 1 [MobilenetV2/expanded_conv_4/project/add_fold]</span><br><span class="line"> ADD 68.621 0.097 0.106 0.092% 59.757% 0.000 1 [MobilenetV2/expanded_conv_4/add]</span><br><span class="line"> CONV_2D 68.728 2.234 2.056 1.789% 61.546% 0.000 1 [MobilenetV2/expanded_conv_5/expand/Relu6]</span><br><span class="line"> DEPTHWISE_CONV_2D 70.786 1.135 1.180 1.027% 62.573% 0.000 1 [MobilenetV2/expanded_conv_5/depthwise/Relu6]</span><br><span class="line"> CONV_2D 71.968 1.073 1.174 1.022% 63.594% 0.000 1 [MobilenetV2/expanded_conv_5/project/add_fold]</span><br><span class="line"> ADD 73.145 0.096 0.098 0.086% 63.680% 0.000 1 [MobilenetV2/expanded_conv_5/add]</span><br><span class="line"> CONV_2D 73.244 1.992 2.172 1.890% 65.570% 0.000 1 [MobilenetV2/expanded_conv_6/expand/Relu6]</span><br><span class="line"> DEPTHWISE_CONV_2D 75.419 0.409 0.469 0.408% 65.978% 0.000 1 [MobilenetV2/expanded_conv_6/depthwise/Relu6]</span><br><span class="line"> CONV_2D 75.889 0.395 0.445 0.387% 66.366% 0.000 1 [MobilenetV2/expanded_conv_6/project/add_fold]</span><br><span class="line"> CONV_2D 76.335 1.277 1.172 1.020% 67.386% 0.000 1 [MobilenetV2/expanded_conv_7/expand/Relu6]</span><br><span class="line"> DEPTHWISE_CONV_2D 77.509 0.778 0.624 0.543% 67.929% 0.000 1 [MobilenetV2/expanded_conv_7/depthwise/Relu6]</span><br><span class="line"> CONV_2D 78.135 1.041 0.779 0.678% 68.606% 0.000 1 [MobilenetV2/expanded_conv_7/project/add_fold]</span><br><span class="line"> ADD 78.915 0.067 0.054 0.047% 68.653% 0.000 1 [MobilenetV2/expanded_conv_7/add]</span><br><span class="line"> CONV_2D 78.969 1.059 1.147 0.998% 69.651% 0.000 1 [MobilenetV2/expanded_conv_8/expand/Relu6]</span><br><span class="line"> DEPTHWISE_CONV_2D 80.118 0.639 0.619 0.539% 70.190% 0.000 1 [MobilenetV2/expanded_conv_8/depthwise/Relu6]</span><br><span class="line"> CONV_2D 80.738 0.620 0.767 0.667% 70.857% 0.000 1 [MobilenetV2/expanded_conv_8/project/add_fold]</span><br><span class="line"> ADD 81.506 0.052 0.051 0.044% 70.902% 0.000 1 [MobilenetV2/expanded_conv_8/add]</span><br><span class="line"> CONV_2D 81.558 1.271 1.139 0.991% 71.892% 0.000 1 [MobilenetV2/expanded_conv_9/expand/Relu6]</span><br><span class="line"> DEPTHWISE_CONV_2D 82.699 0.595 0.582 0.506% 72.399% 0.000 1 [MobilenetV2/expanded_conv_9/depthwise/Relu6]</span><br><span class="line"> CONV_2D 83.282 0.853 0.750 0.652% 73.051% 0.000 1 [MobilenetV2/expanded_conv_9/project/add_fold]</span><br><span class="line"> ADD 84.033 0.055 0.053 0.046% 73.097% 0.000 1 [MobilenetV2/expanded_conv_9/add]</span><br><span class="line"> CONV_2D 84.087 1.078 1.127 0.981% 74.078% 0.000 1 [MobilenetV2/expanded_conv_10/expand/Relu6]</span><br><span class="line"> DEPTHWISE_CONV_2D 85.216 0.635 0.595 0.518% 74.596% 0.000 1 [MobilenetV2/expanded_conv_10/depthwise/Relu6]</span><br><span class="line"> CONV_2D 85.813 1.022 1.106 0.963% 75.559% 0.000 1 [MobilenetV2/expanded_conv_10/project/add_fold]</span><br><span class="line"> CONV_2D 86.921 2.031 2.034 1.770% 77.328% 0.000 1 [MobilenetV2/expanded_conv_11/expand/Relu6]</span><br><span class="line"> DEPTHWISE_CONV_2D 88.957 0.999 0.980 0.852% 78.181% 0.000 1 [MobilenetV2/expanded_conv_11/depthwise/Relu6]</span><br><span class="line"> CONV_2D 89.939 1.476 1.588 1.382% 79.562% 0.000 1 [MobilenetV2/expanded_conv_11/project/add_fold]</span><br><span class="line"> ADD 91.529 0.074 0.077 0.067% 79.629% 0.000 1 [MobilenetV2/expanded_conv_11/add]</span><br><span class="line"> CONV_2D 91.607 2.472 2.057 1.790% 81.419% 0.000 1 [MobilenetV2/expanded_conv_12/expand/Relu6]</span><br><span class="line"> DEPTHWISE_CONV_2D 93.666 1.046 0.959 0.834% 82.253% 0.000 1 [MobilenetV2/expanded_conv_12/depthwise/Relu6]</span><br><span class="line"> CONV_2D 94.627 1.548 1.564 1.361% 83.614% 0.000 1 [MobilenetV2/expanded_conv_12/project/add_fold]</span><br><span class="line"> ADD 96.193 0.077 0.079 0.068% 83.683% 0.000 1 [MobilenetV2/expanded_conv_12/add]</span><br><span class="line"> CONV_2D 96.272 2.107 2.032 1.768% 85.451% 0.000 1 [MobilenetV2/expanded_conv_13/expand/Relu6]</span><br><span class="line"> DEPTHWISE_CONV_2D 98.306 0.318 0.319 0.278% 85.729% 0.000 1 [MobilenetV2/expanded_conv_13/depthwise/Relu6]</span><br><span class="line"> CONV_2D 98.626 0.717 0.732 0.637% 86.365% 0.000 1 [MobilenetV2/expanded_conv_13/project/add_fold]</span><br><span class="line"> CONV_2D 99.359 1.280 1.413 1.230% 87.595% 0.000 1 [MobilenetV2/expanded_conv_14/expand/Relu6]</span><br><span class="line"> DEPTHWISE_CONV_2D 100.774 0.332 0.364 0.316% 87.911% 0.000 1 [MobilenetV2/expanded_conv_14/depthwise/Relu6]</span><br><span class="line"> CONV_2D 101.142 1.191 1.238 1.077% 88.989% 0.000 1 [MobilenetV2/expanded_conv_14/project/add_fold]</span><br><span class="line"> ADD 102.382 0.037 0.039 0.034% 89.023% 0.000 1 [MobilenetV2/expanded_conv_14/add]</span><br><span class="line"> CONV_2D 102.421 1.305 1.459 1.270% 90.292% 0.000 1 [MobilenetV2/expanded_conv_15/expand/Relu6]</span><br><span class="line"> DEPTHWISE_CONV_2D 103.883 0.369 0.391 0.340% 90.633% 0.000 1 [MobilenetV2/expanded_conv_15/depthwise/Relu6]</span><br><span class="line"> CONV_2D 104.275 1.214 1.239 1.078% 91.711% 0.000 1 [MobilenetV2/expanded_conv_15/project/add_fold]</span><br><span class="line"> ADD 105.516 0.036 0.036 0.032% 91.743% 0.000 1 [MobilenetV2/expanded_conv_15/add]</span><br><span class="line"> CONV_2D 105.552 1.312 1.405 1.222% 92.965% 0.000 1 [MobilenetV2/expanded_conv_16/expand/Relu6]</span><br><span class="line"> DEPTHWISE_CONV_2D 106.960 0.352 0.401 0.349% 93.314% 0.000 1 [MobilenetV2/expanded_conv_16/depthwise/Relu6]</span><br><span class="line"> CONV_2D 107.362 2.322 2.311 2.011% 95.325% 0.000 1 [MobilenetV2/expanded_conv_16/project/add_fold]</span><br><span class="line"> CONV_2D 109.675 3.883 3.400 2.958% 98.283% 0.000 1 [MobilenetV2/Conv_1/Relu6]</span><br><span class="line"> AVERAGE_POOL_2D 113.078 0.129 0.125 0.109% 98.392% 0.000 1 [MobilenetV2/Logits/AvgPool]</span><br><span class="line"> CONV_2D 113.204 1.732 1.844 1.604% 99.996% 0.000 1 [MobilenetV2/Logits/Conv2d_1c_1x1/BiasAdd]</span><br><span class="line"> RESHAPE 115.050 0.005 0.005 0.004% 100.000% 0.000 1 [output]</span><br><span class="line"></span><br><span class="line">============================== Top by Computation Time ==============================</span><br><span class="line"> [node <span class="built_in">type</span>] [start] [first] [avg ms] [%] [cdf%] [mem KB] [<span class="built_in">times</span> called] [Name]</span><br><span class="line"> CONV_2D 14.688 12.247 17.846 15.529% 15.529% 0.000 1 [MobilenetV2/expanded_conv_1/expand/Relu6]</span><br><span class="line"> CONV_2D 53.607 12.993 7.827 6.811% 22.340% 0.000 1 [MobilenetV2/expanded_conv_3/expand/Relu6]</span><br><span class="line"> CONV_2D 38.493 12.619 7.820 6.805% 29.145% 0.000 1 [MobilenetV2/expanded_conv_2/expand/Relu6]</span><br><span class="line"> CONV_2D 0.000 5.567 7.237 6.297% 35.442% 0.000 1 [MobilenetV2/Conv/Relu6]</span><br><span class="line"> DEPTHWISE_CONV_2D 7.241 3.518 3.726 3.243% 38.684% 0.000 1 [MobilenetV2/expanded_conv/depthwise/Relu6]</span><br><span class="line"> CONV_2D 10.971 2.399 3.711 3.229% 41.913% 0.000 1 [MobilenetV2/expanded_conv/project/add_fold]</span><br><span class="line"> DEPTHWISE_CONV_2D 46.318 4.750 3.683 3.205% 45.118% 0.000 1 [MobilenetV2/expanded_conv_2/depthwise/Relu6]</span><br><span class="line"> DEPTHWISE_CONV_2D 32.539 2.594 3.486 3.033% 48.151% 0.000 1 [MobilenetV2/expanded_conv_1/depthwise/Relu6]</span><br><span class="line"> CONV_2D 109.675 3.883 3.400 2.958% 51.109% 0.000 1 [MobilenetV2/Conv_1/Relu6]</span><br><span class="line"> CONV_2D 50.005 4.853 3.305 2.876% 53.985% 0.000 1 [MobilenetV2/expanded_conv_2/project/add_fold]</span><br><span class="line"></span><br><span class="line">Number of nodes executed: 65</span><br><span class="line">============================== Summary by node <span class="built_in">type</span> ==============================</span><br><span class="line"> [Node <span class="built_in">type</span>] [count] [avg ms] [avg %] [cdf %] [mem KB] [<span class="built_in">times</span> called]</span><br><span class="line"> CONV_2D 36 92.625 80.619% 80.619% 0.000 36</span><br><span class="line"> DEPTHWISE_CONV_2D 17 21.256 18.501% 99.120% 0.000 17</span><br><span class="line"> ADD 10 0.882 0.768% 99.888% 0.000 10</span><br><span class="line"> AVERAGE_POOL_2D 1 0.125 0.109% 99.997% 0.000 1</span><br><span class="line"> RESHAPE 1 0.004 0.003% 100.000% 0.000 1</span><br><span class="line"></span><br><span class="line">Timings (microseconds): count=50 first=118487 curr=113927 min=88158 max=129072 avg=114924 std=7657</span><br><span class="line">Memory (bytes): count=0</span><br><span class="line">65 nodes observed</span><br></pre></td></tr></table></figure><h2 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h2><ol><li>C++11编译异常</li></ol><p>bazel编译命令后,加上<code>--cxxopt='--std=c++11'</code> 选项</p><ol start="2"><li>Bazel版本过低或者过高</li></ol><p>安装0.24.1版本的bazel</p></div><footer class="post-footer"><div class="post-eof"></div></footer></article></div><div class="post-block"><article itemscope itemtype="http://schema.org/Article" class="post-content"><link itemprop="mainEntityOfPage" href="http://www.vectoros.club/post/dd926e02.html"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="image" content="/uploads/avatar.webp"><meta itemprop="name" content="Vectoros"><meta itemprop="description" content=""></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="Keep Learning"></span><header class="post-header"><h2 class="post-title" itemprop="name headline"><a href="/post/dd926e02.html" class="post-title-link" itemprop="url">Convert Keras h5 model to TFLite model</a></h2><div class="post-meta-container"><div class="post-meta"><span class="post-meta-item"><span class="post-meta-item-icon"><i class="far fa-calendar"></i> </span><span class="post-meta-item-text">发表于</span> <time title="创建时间:2019-05-05 21:15:09" itemprop="dateCreated datePublished" datetime="2019-05-05T21:15:09+08:00">2019-05-05</time> </span><span class="post-meta-item"><span class="post-meta-item-icon"><i class="far fa-folder"></i> </span><span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Python/" itemprop="url" rel="index"><span itemprop="name">Python</span></a> </span>, <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Python/TensorFlow/" itemprop="url" rel="index"><span itemprop="name">TensorFlow</span></a> </span>, <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Python/TensorFlow/Keras/" itemprop="url" rel="index"><span itemprop="name">Keras</span></a></span></span></div></div></header><div class="post-body" itemprop="articleBody"><p>目前在移动端(Android)使用比较广泛的深度模型框架是TFLite,这个也是Google大力推广的。但是目前很多高效的网络都没有官方的TensorFlow版本,所以在使用的时候,我们需要将其他格式的模型,转换成TFLite格式。<br>好在Google提供了非常全的转换工具,在最新版本中,Keras已经成为了官方推荐的前端。</p><h2 id="模型转换前的准备"><a href="#模型转换前的准备" class="headerlink" title="模型转换前的准备"></a>模型转换前的准备</h2><ul><li>确定源模型的格式</li><li>确定源模型的输入名称,输入尺寸</li><li>确定源模型的输出名称,输出尺寸</li></ul><h2 id="下面以Yolov3的cfg和weights文件转换成TFLite为例"><a href="#下面以Yolov3的cfg和weights文件转换成TFLite为例" class="headerlink" title="下面以Yolov3的cfg和weights文件转换成TFLite为例"></a>下面以Yolov3的cfg和weights文件转换成TFLite为例</h2><p>Yolo的Backbone是Darknet,首先需要转换成支持的keras模型</p><ol><li>转换成Keras h5 格式</li></ol><p>使用修改后的工具<a target="_blank" rel="noopener" href="https://github.com/vectoros/keras-yolo3">keras_yolov3</a>, 用里面的convert.py文件,将模型转成keras的h5格式</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">wget https://pjreddie.com/media/files/yolov3.weights</span><br><span class="line">python convert.py yolov3.cfg yolov3.weights <span class="number">320</span> model_data/yolov3.h5</span><br></pre></td></tr></table></figure><ol start="2"><li>读取转换后模型的参数</li></ol><p>转换模型函数需要提供输出和输出</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_output_names</span>(<span class="params">keras_model</span>):</span></span><br><span class="line"> outputs = keras_model.outputs</span><br><span class="line"> output_names = []</span><br><span class="line"> <span class="keyword">for</span> _output <span class="keyword">in</span> outputs:</span><br><span class="line"> output_names.append(_output.name[:-<span class="number">2</span>])</span><br><span class="line"> <span class="keyword">return</span> output_names</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_input_names</span>(<span class="params">keras_model</span>):</span></span><br><span class="line"> inputs = keras_model.inputs</span><br><span class="line"> input_names = []</span><br><span class="line"> <span class="keyword">for</span> _<span class="built_in">input</span> <span class="keyword">in</span> inputs:</span><br><span class="line"> input_names.append(_<span class="built_in">input</span>.name[:-<span class="number">2</span>])</span><br><span class="line"> <span class="keyword">return</span> input_names</span><br></pre></td></tr></table></figure><ol start="3"><li>使用官方提供的<code>lite.TFLiteConverter.from_keras_model_file</code>转换模型</li></ol><p>调用官方提供的方法转换模型</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">keras_to_tflite</span>(<span class="params">input_keras_model_file, output_tflite_file</span>):</span></span><br><span class="line"> keras_model = load_model(input_keras_model_file)</span><br><span class="line"> input_names = get_input_names(keras_model)</span><br><span class="line"> output_names = get_output_names(keras_model)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"input names:"</span>, input_names, <span class="string">" shapes:"</span>, keras_model.input_shape)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"output names:"</span>, output_names, <span class="string">" shapes:"</span>, keras_model.output_shape)</span><br><span class="line"> converter = lite.TFLiteConverter.from_keras_model_file(model_file=input_keras_model_file,</span><br><span class="line"> input_arrays=input_names,</span><br><span class="line"> output_arrays=output_names)</span><br><span class="line"> model = converter.convert()</span><br><span class="line"> file = <span class="built_in">open</span>(output_tflite_file, <span class="string">"wb"</span>)</span><br><span class="line"> file.write(model)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"save tflite file to: "</span>, output_tflite_file)</span><br></pre></td></tr></table></figure><ol start="4"><li>获取转换后的模型</li></ol><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span>():</span></span><br><span class="line"> keras_model_file = <span class="string">"./model_data/yolov3.h5"</span></span><br><span class="line"> tflite_model_file = <span class="string">"./model_data/yolov3.tflite"</span></span><br><span class="line"> keras_to_tflite(keras_model_file, tflite_model_file)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line"> main()</span><br></pre></td></tr></table></figure><h2 id="预告"><a href="#预告" class="headerlink" title="预告"></a>预告</h2><p>如何在PC端验证测试转换后的TFLite模型</p></div><footer class="post-footer"><div class="post-eof"></div></footer></article></div><nav class="pagination"><span class="page-number current">1</span><a class="page-number" href="/page/2/">2</a><a class="extend next" rel="next" href="/page/2/"><i class="fa fa-angle-right" aria-label="下一页"></i></a></nav><script>window.addEventListener('tabs:register', () => {
let { activeClass } = CONFIG.comments;
if (CONFIG.comments.storage) {
activeClass = localStorage.getItem('comments_active') || activeClass;
}
if (activeClass) {
const activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
if (activeTab) {
activeTab.click();
}
}
});
if (CONFIG.comments.storage) {
window.addEventListener('tabs:click', event => {
if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
const commentClass = event.target.classList[1];
localStorage.setItem('comments_active', commentClass);
});
}</script></div></main><footer class="footer"><div class="footer-inner"><div class="copyright">© <span itemprop="copyrightYear">2023</span> <span class="with-love"><i class="fa fa-heart"></i> </span><span class="author" itemprop="copyrightHolder">Vectoros</span></div><div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.js.org/muse/" class="theme-link" rel="noopener" target="_blank">NexT.Muse</a> 强力驱动</div></div></footer><script src="https://cdn.jsdelivr.net/npm/animejs@3.2.1/lib/anime.min.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/schemes/muse.js"></script><script src="/js/next-boot.js"></script><script src="/js/local-search.js"></script><script src="https://cdn.jsdelivr.net/npm/quicklink@2.1.0/dist/quicklink.umd.js"></script><script>window.addEventListener('load', () => {
quicklink.listen({
timeout : 3000,
priority: true,
ignores : [uri => uri.includes('#'),uri => uri === 'http://www.vectoros.club/',]
});
});</script></body></html>