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>
阅读全文
0 0
- Android Fingerprint -- Enroll流程
- Android Fingerprint -- Enroll流程
- Android Fingerprint -- Enroll流程
- Android Fingerprint完全解析(二) :Fingerprint启动流程
- Android Fingerprint完全解析(二) :Fingerprint启动流程
- 指纹识别分析之enroll流程
- android SHA1 fingerPrint
- android M fingerprint 解析
- Android Fingerprint完全解析(一) :Fingerprint整体框架
- Android Fingerprint完全解析(三) :Fingerprint Hal层分析
- Android Fingerprint完全解析(一) :Fingerprint整体框架
- Android Fingerprint完全解析(三) :Fingerprint Hal层分析
- Android Fingerprint -- HAL层的初始化工作
- android开发中Fingerprint模块浅析
- Android Fingerprint -- HAL层的初始化工作
- android开发中Fingerprint模块浅析
- android开发中Fingerprint模块浅析
- Android Fingerprint -- HAL层的初始化工作
- 开源的RippleLayout,点击产生波浪涟漪效果
- ecshop之transport和jquery冲突之完美解决方案
- 【实践】端到端的OCR:验证码识别
- Java菜鸟成长之路__Day_2_Java_方法
- Redis原理详解
- Android Fingerprint -- Enroll流程
- vue2 子组件调用父组件中的方法
- centos7 最小化安装后无法上网,需要先开启网络服务
- linux之nautilus .命令浏览当前文件目录
- centos7 firewall 防火墙 命令
- 响铃:体育运动社交,到底是伪需求还是真未来?
- 内存管理检查方法和工具
- Win32API学习笔记第五章(二)
- C语言实现单向链表