Android Fingerprint -- Enroll流程

来源:互联网 发布:如何看待网络言论作文 编辑:程序博客网 时间:2024/05/17 21:05
    <div class="article_title">            <span class="ico ico_type_Repost"></span>    <h1>        <span class="link_title"><a href="/sky1203850702/article/details/52849018">        Android Fingerprint -- Enroll流程                           </a>        </span>    </h1></div>           <div class="article_manage clearfix">        <div class="article_l">            <span class="link_categories">            标签:              <a href="http://www.csdn.net/tag/fingerprint" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">fingerprint</a><a href="http://www.csdn.net/tag/android" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">android</a><a href="http://www.csdn.net/tag/%e6%8c%87%e7%ba%b9%e8%af%86%e5%88%ab" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">指纹识别</a><a href="http://www.csdn.net/tag/%e6%8c%87%e7%ba%b9%e5%bd%95%e5%85%a5" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">指纹录入</a><a href="http://www.csdn.net/tag/enroll" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">enroll</a>            </span>        </div>        <div class="article_r">            <span class="link_postdate">2016-10-18 15:01</span>            <span class="link_view" title="阅读次数">1391人阅读</span>            <span class="link_comments" title="评论次数"> <a href="#comments" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_pinglun'])">评论</a>(1)</span>            <span class="link_collect tracking-ad" data-mod="popu_171"> <a href="javascript:void(0);" onclick="javascript:collectArticle('Android+Fingerprint+--+Enroll%e6%b5%81%e7%a8%8b','52849018');return false;" title="收藏" target="_blank">收藏</a></span>             <span class="link_report"> <a href="#report" onclick="javascript:report(52849018,2);return false;" title="举报">举报</a></span>        </div>    </div>    <div class="embody" style="display:none" id="embody">        <span class="embody_t">本文章已收录于:</span>        <div class="embody_c" id="lib" value="{"err":0,"msg":"ok","data":[]}"></div>    </div>    <style type="text/css">                    .embody{                padding:10px 10px 10px;                margin:0 -20px;                border-bottom:solid 1px #ededed;                            }            .embody_b{                margin:0 ;                padding:10px 0;            }            .embody .embody_t,.embody .embody_c{                display: inline-block;                margin-right:10px;            }            .embody_t{                font-size: 12px;                color:#999;            }            .embody_c{                font-size: 12px;            }            .embody_c img,.embody_c em{                display: inline-block;                vertical-align: middle;                           }             .embody_c img{                               width:30px;                height:30px;            }            .embody_c em{                margin: 0 20px 0 10px;                color:#333;                font-style: normal;            }    </style>    <script type="text/javascript">        $(function () {            try            {                var lib = eval("("+$("#lib").attr("value")+")");                var html = "";                if (lib.err == 0) {                    $.each(lib.data, function (i) {                        var obj = lib.data[i];                        //html += '<img src="' + obj.logo + '"/>' + obj.name + "  ";                        html += ' <a href="' + obj.url + '" target="_blank">';                        html += ' <img src="' + obj.logo + '">';                        html += ' <em><b>' + obj.name + '</b></em>';                        html += ' </a>';                    });                    if (html != "") {                        setTimeout(function () {                            $("#lib").html(html);                                                  $("#embody").show();                        }, 100);                    }                }                  } catch (err)            { }                    });    </script>      <div class="category clearfix">        <div class="category_l">           <img src="http://static.blog.csdn.net/images/category_icon.jpg">            <span>分类:</span>        </div>        <div class="category_r">                    <label onclick="GetCategoryArticles('2575735','sky1203850702','top','52849018');">                        <span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_fenlei']);">Android开发<em>(63)</em></span>                      <img class="arrow-down" src="http://static.blog.csdn.net/images/arrow_triangle _down.jpg" style="display:inline;">                      <img class="arrow-up" src="http://static.blog.csdn.net/images/arrow_triangle_up.jpg" style="display:none;">                        <div class="subItem">                            <div class="subItem_t"><a href="http://blog.csdn.net/sky1203850702/article/category/2575735" target="_blank">作者同类文章</a><i class="J_close">X</i></div>                            <ul class="subItem_l" id="top_2575735">                                                        </ul>                        </div>                    </label>                                        <label onclick="GetCategoryArticles('5638317','sky1203850702','top','52849018');">                        <span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_fenlei']);">技术类<em>(21)</em></span>                      <img class="arrow-down" src="http://static.blog.csdn.net/images/arrow_triangle _down.jpg" style="display:inline;">                      <img class="arrow-up" src="http://static.blog.csdn.net/images/arrow_triangle_up.jpg" style="display:none;">                        <div class="subItem">                            <div class="subItem_t"><a href="http://blog.csdn.net/sky1203850702/article/category/5638317" target="_blank">作者同类文章</a><i class="J_close">X</i></div>                            <ul class="subItem_l" id="top_5638317">                                                        </ul>                        </div>                    </label>                            </div>    </div>           <div style="clear:both"></div><div style="border:solid 1px #ccc; background:#eee; float:left; min-width:200px;padding:4px 10px;"><p style="text-align:right;margin:0;"><span style="float:left;">目录<a href="#" title="系统根据文章中H1到H6标签自动生成文章目录">(?)</a></span><a href="#" onclick="javascript:return openct(this);" title="展开">[+]</a></p><ol style="display:none;margin-left:14px;padding-left:14px;line-height:160%;"><li><a href="#t0">一preEnroll</a></li><li><a href="#t1">二enroll</a></li><li><a href="#t2">三postEnroll</a></li></ol></div><div style="clear:both"></div><div id="article_content" class="article_content tracking-ad" data-mod="popu_307" data-dsm="post"><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">Enroll流程主要的工作是在hal层以下完成的。对于应用层和framwork层的流程就不做详细分析了。</p><h3 id="一preenroll" style="margin:0px; padding:0px; font-size:16px; line-height:1.5; font-family:Verdana,Arial,Helvetica,sans-serif"><a name="t0" target="_blank"></a>一、preEnroll</h3><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">点击设置中的添加指纹,setting就会调到fingerprintd的preEnroll接口。preEnroll会在指纹TA中生成并保存一个64位的随机数。这个随机数有两个用途:</p><ul style="margin:0px 0px 0px 30px; padding:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px"><li style="margin:0px; padding:0px; list-style:disc"><p style="margin:10px auto; padding-top:0px; padding-bottom:0px">返回给上层,用于填充enroll中的authenticated token challenge。</p></li><li style="margin:0px; padding:0px; list-style:disc"><p style="margin:10px auto; padding-top:0px; padding-bottom:0px">TA会用它对下次enroll做初步校验,保证enroll没有被第三方篡改。</p></li></ul><h3 id="二enroll" style="margin:0px; padding:0px; font-size:16px; line-height:1.5; font-family:Verdana,Arial,Helvetica,sans-serif"><a name="t1" target="_blank"></a>二、enroll</h3><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">1 、我们先看一下 fingerprint.h对enroll接口的定义:</p><pre style="margin-top:10px; margin-bottom:10px; padding:0px; white-space:pre-wrap; word-wrap:break-word; color:rgb(51,51,51); font-size:13.3333px; background-color:rgb(255,255,255)"><code class="hljs cpp" style="margin:auto; vertical-align:middle; display:block; height:auto; overflow-x:auto; color:rgb(0,0,0); padding:5px!important; line-height:1.5!important; font-family:"Courier New",sans-serif!important; font-size:12px!important; border:1px solid rgb(204,204,204)!important"><span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">int</span> (*enroll)(<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">struct</span> fingerprint_device *dev, <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">const</span> <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">hw_auth_token_t</span> *hat,                <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">uint32_t</span> gid, <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">uint32_t</span> timeout_sec);</code></pre><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">1.1 、hw_auth_token_t:保证此次enroll的合法性,我们具体看一下<a href="http://lib.csdn.net/base/android" class="replace_word" title="Android知识库" target="_blank" style="color:#df3434; font-weight:bold;">Android</a>怎么定义此结构体的。<br style="margin:0px; padding:0px"><img src="http://images2015.cnblogs.com/blog/984967/201609/984967-20160914142057617-98939389.jpg" alt="" style="margin:0px; padding:0px; border:0px; max-width:900px"></p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">AuthToken version :此token的版本号</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">Challenge:就是前面调用preEnroll的到的64位随机数,防止此次enroll被第三方假冒</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">User SID : 安全性id,不是<a href="http://lib.csdn.net/base/android" class="replace_word" title="Android知识库" target="_blank" style="color:#df3434; font-weight:bold;">android</a> user id</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">Athenticator ID: 用于标明不同的认证权限</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">Authenticator Type:0x00表示Gatekeeper,0x01表示Fingerprint</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">Timestamp:最近一次开机时间戳</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">AuthToken HMAC key: 用一个特殊的key和SHA-256<a href="http://lib.csdn.net/base/datastructure" class="replace_word" title="算法与数据结构知识库" target="_blank" style="color:#df3434; font-weight:bold;">算法</a>去计算前面一堆参数后,得到的一个 hmac值,保证前面参数的合法性和安全性。</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">1.2. gid:说明是哪个用户注册指纹(anroid支持多用户)。</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">1.3. timeout_sec:超时设置。</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">2、上层调用enroll接口,一直将上述参数传递到指纹TA中。TA拿到参数之后会先检查参数是否合法。我们看看TA是怎样检查的:</p><pre style="margin-top:10px; margin-bottom:10px; padding:0px; white-space:pre-wrap; word-wrap:break-word; color:rgb(51,51,51); font-size:13.3333px; background-color:rgb(255,255,255)"><code class="hljs php" style="margin:auto; vertical-align:middle; display:block; height:auto; overflow-x:auto; color:rgb(0,0,0); padding:5px!important; line-height:1.5!important; font-family:"Courier New",sans-serif!important; font-size:12px!important; border:1px solid rgb(204,204,204)!important"><span class="hljs-comment" style="margin:0px; padding:0px; color:green">//核对传递下来的token->challenge与之前preEnroll阶段保存的g_challenge是否相同</span><span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (token && token->challenge == g_challenge) {    g_user_id = token->user_id;} <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">else</span> {    LOGE(LOG_TAG <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"[%s] invalid or null auth token"</span>, __func__);}<span class="hljs-comment" style="margin:0px; padding:0px; color:green">//检测token版本是否相同</span><span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (token && token->version != cmd->data.enroll.system_auth_token_version) {    LOGE(LOG_TAG <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"[%s] invalid hat version code detected"</span>, __func__);    err = ERROR_INVALID_HAT_VERSION;    <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">break</span>;}<span class="hljs-comment" style="margin:0px; padding:0px; color:green">//检测authenticator_type版本是否相同</span><span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (token && (token->authenticator_type & GF_HW_AUTH_FINGERPRINT)) {    LOGE(LOG_TAG <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"[%s] invalid challenge detected"</span>, __func__);    err = ERROR_INVALID_CHALLENGE;    <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">break</span>;}<span class="hljs-comment" style="margin:0px; padding:0px; color:green">/*token中,除了hmac之外的数据取出来,然后拿这部分数据用key和相应加密算法生成hmac*/</span>cpl_memcpy(&hat, token, sizeof(gf_hw_auth_token_t));cpl_memset(&(hat.hmac), <span class="hljs-number" style="margin:0px; padding:0px">0</span>, hmac_len);generate_hmac(&hat);<span class="hljs-comment" style="margin:0px; padding:0px; color:green">/*比对新生成的hmac和之前上层传递下来token中自带的hmac是否相同,如果相同则认为没本次enroll合法,接下来IC就会切换到一种采图的工作模式*/</span><span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (<span class="hljs-number" style="margin:0px; padding:0px">0</span> != cpl_memcmp(hat.hmac, token->hmac, hmac_len)) {    LOGE(LOG_TAG <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"[%s] token authenticate failed"</span>, __func__);    err = ERROR_UNTRUSTED_ENROLL;    <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">break</span>;}</code></pre><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">3、验证完参数合法之后,TA会将指纹IC切换到一种等待手指按下采图的工作模式。此时一旦手指按下,会进入中断处理函数,该函数主要的工作流程如下图:<br style="margin:0px; padding:0px"><img src="http://images2015.cnblogs.com/blog/984967/201609/984967-20160914142116945-2056315233.jpg" alt="" style="margin:0px; padding:0px; border:0px; max-width:900px"></p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">从等待手指按下开始,到收到中断读取数据,送算法处理,然后保存图像数据为模板,上报注册进度等消息给上层,最后等待手指抬起。这个过程会一直循环,直到模板建立完成后上报注册完成消息给上层,enroll才算结束了。</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">4、因为读取数据,算法分析等过程都涉及IC厂商的商业机密,所以不能在此分享。</p><h3 id="三postenroll" style="margin:0px; padding:0px; font-size:16px; line-height:1.5; font-family:Verdana,Arial,Helvetica,sans-serif"><a name="t2" target="_blank"></a>三、postEnroll</h3><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">postEnroll主要工作是更新一下TA中保存的Challenge。</p>   </div><!-- Baidu Button BEGIN --><div class="bdsharebuttonbox tracking-ad bdshare-button-style0-16" style="float: right;" data-mod="popu_172" data-bd-bind="1498125154330"><a href="#" class="bds_more" data-cmd="more" style="background-position:0 0 !important; background-image: url(http://bdimg.share.baidu.com/static/api/img/share/icons_0_16.png?v=d754dcc0.png) !important" target="_blank"></a><a href="#" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间" style="background-position:0 -52px !important" target="_blank"></a><a href="#" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博" style="background-position:0 -104px !important" target="_blank"></a><a href="#" class="bds_tqq" data-cmd="tqq" title="分享到腾讯微博" style="background-position:0 -260px !important" target="_blank"></a><a href="#" class="bds_renren" data-cmd="renren" title="分享到人人网" style="background-position:0 -208px !important" target="_blank"></a><a href="#" class="bds_weixin" data-cmd="weixin" title="分享到微信" style="background-position:0 -1612px !important" target="_blank"></a></div><script>window._bd_share_config = { "common": { "bdSnsKey": {}, "bdText": "", "bdMini": "1", "bdMiniList": false, "bdPic": "", "bdStyle": "0", "bdSize": "16" }, "share": {} }; with (document) 0[(getElementsByTagName('head')[0] || body).appendChild(createElement('script')).src = 'http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion=' + ~(-new Date() / 36e5)];</script><!-- Baidu Button END -->       <!--172.16.140.11--><!-- Baidu Button BEGIN --><script type="text/javascript" id="bdshare_js" data="type=tools&uid=1536434" src="http://bdimg.share.baidu.com/static/js/bds_s_v2.js?cdnversion=416146"></script><script type="text/javascript">    document.getElementById("bdshell_js").src = "http://bdimg.share.baidu.com/static/js/shell_v2.js?cdnversion=" + Math.ceil(new Date()/3600000)</script><!-- Baidu Button END -->         <div id="digg" articleid="52849018">            <dl id="btnDigg" class="digg digg_enable" onclick="btndigga();">                                <dt>顶</dt>                <dd>1</dd>            </dl>                                     <dl id="btnBury" class="digg digg_enable" onclick="btnburya();">                                <dt>踩</dt>                <dd>0</dd>                           </dl>                    </div>     <div class="tracking-ad" data-mod="popu_222"><a href="javascript:void(0);" target="_blank"> </a>   </div>    <div class="tracking-ad" data-mod="popu_223"> <a href="javascript:void(0);" target="_blank"> </a></div>    <script type="text/javascript">                function btndigga() {                    $(".tracking-ad[data-mod='popu_222'] a").click();                }                function btnburya() {                    $(".tracking-ad[data-mod='popu_223'] a").click();                }            </script>   <ul class="article_next_prev">                <li class="prev_article"><span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_shangyipian']);location.href='/sky1203850702/article/details/52778881';">上一篇</span><a href="/sky1203850702/article/details/52778881" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_shangyipian'])">C语言opendir()函数:打开目录函数</a></li>                <li class="next_article"><span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_xiayipian']);location.href='/sky1203850702/article/details/53434914';">下一篇</span><a href="/sky1203850702/article/details/53434914" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_xiayipian'])">Android 密钥库系统</a></li>    </ul>    <div style="clear:both; height:10px;"></div>            <div class="similar_article">                    <h4></h4>                    <div class="similar_c" style="margin:20px 0px 0px 0px">                        <div class="similar_c_t">                            相关文章推荐                        </div>                                           <div class="similar_wrap tracking-ad" data-mod="popu_36">                                                   <ul class="similar_list fl">                                       <li>                                       <em>•</em>                                       <a href="http://dawuafang.iteye.com/blog/2254695" title="Android View绘制流程" strategy="" target="_blank">Android View绘制流程</a>                                   </li>                                   <li>                                       <em>•</em>                                       <a href="http://lasombra.iteye.com/blog/847329" title="FingerPrint" strategy="" target="_blank">FingerPrint</a>                                   </li>                                   <li>                                       <em>•</em>                                       <a href="http://yanwenjinhaha.iteye.com/blog/2162542" title="android vold架构详解(2)_Kernel层向上发送消息处理流程" strategy="" target="_blank">android vold架构详解(2)_Kernel层向上发送消息处理流程</a>                                   </li>                                   <li>                                       <em>•</em>                                       <a href="http://blog.csdn.net/MrCharles/article/details/70432405" title="FingerPrint Fuzzy Vault Matlab实践" strategy="" target="_blank">FingerPrint Fuzzy Vault Matlab实践</a>                                   </li>                                   <li>                                       <em>•</em>                                       <a href="http://justcoding.iteye.com/blog/2116837" title="Moodle: 登记学生,检测学生是否存在在课程 Check if user is enrolled or enroll a user in course" strategy="" target="_blank">Moodle: 登记学生,检测学生是否存在在课程 Check if user is enrolled or enroll a user in course</a>                                   </li>                            </ul>                              <ul class="similar_list fr">                                         <li>                                       <em>•</em>                                       <a href="http://talent2012.iteye.com/blog/2095034" title="android 4.4 MT(去电)流程" strategy="" target="_blank">android 4.4 MT(去电)流程</a>                                   </li>                                   <li>                                       <em>•</em>                                       <a href="http://zhaoxin1943.iteye.com/blog/2174763" title="android事件处理流程" strategy="" target="_blank">android事件处理流程</a>                                   </li>                                   <li>                                       <em>•</em>                                       <a href="http://zhoujingheng.iteye.com/blog/2222360" title="Android相机开发流程" strategy="" target="_blank">Android相机开发流程</a>                                   </li>                                   <li>                                       <em>•</em>                                       <a href="http://shangxun.iteye.com/blog/2139430" title="Qt for Android 部署流程分析" strategy="" target="_blank">Qt for Android 部署流程分析</a>                                   </li>                                   <li>                                       <em>•</em>                                       <a href="http://maozhuxigood.iteye.com/blog/2066643" title="Android Camera open运行流程" strategy="" target="_blank">Android Camera open运行流程</a>                                   </li>                            </ul>                        </div>                    </div>                </div>         

原创粉丝点击