Flysands Blog


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 搜索

理解闭包

发表于 2017-01-29 | 分类于 lisp |

1 Lambda the Ultimate

  • 理解闭包 闭包定义:如果一个函数返回另一个函数,而被返回函数又需要外层函数的变量时,不会立即释放 这个变量,而是允许被返回的函数引用这些变量.支持这种机制的语言称为支持闭包机制,而这个内 部函数连同其自由变量就形成了一个闭包.

    (define eq?-c
      (lambda (a)
        (lambda (x)
          (eq? x a))))
    

    以上eq?-c函数就有一个闭包,首先eq?-c满足一个函数返回另一个函数的条件,eq?-c返回一个lambda函数. lambda函数却引用了外部变量a.所以a为自由变量,lambda函数与自由变量a形成了一个闭包. 再看下面这个例子详细理解一下闭包概念.

    (define add-a
      (lambda (a)
        (lambda (x)
          (+ x a))))
    

    这个lambda函数是不完整的,(+ x a)中的a是多少?有两个方法回答这个问题. 第一种叫"动态作用域",a的值决定于函数调用时上下文中a的值. (define a 1) (add-a 1) 以上输出应该为2.因为调用(add-a 1)时,上下文中存在a,并且值为1. 动态作用域的问题是,函数每一次调用相同的参数未必返回相同的值,其返回值还取决于上下文的某些值.这样 的函数具有不确定性. 第二种是"词法作用域",a的值取决于函数定义时上下文中的值. (define fun (add-a 2)) (define a 1) (fun 1) 输出为3.因为定义(lambda (x) (+ x a))时,add-a函数环境中a = 2.所以fun其实的等价(lambda (x) (+ x 2)). 因为fun要"记住"自己定义时a的值为2,所以实现时 (lambda (x) (+ x a))和a = 2 被打包在一块,被称为"闭包",意思是它是完整独立的,仅仅依靠调用时参数求值. 不再依赖调用时的上下文. dynamic scope在每次函数求值的时候都会在这唯一的一个env里查询或更新.而static scope(lexical scope) 是每次函数求值的时候都创建一个新的env,包含了函数定义时候的所能访问到的各种binding.这个新的env连 同那个函数一起.俗称闭包Closure. 词法作用域的函数中遇到既不是形参也不是函数内部定义的局部变量的变量时,去函数定义时的环境中查询. 动态域的函数中遇到既不是形参也不是函数内部定义的局部变量的变量时,到函数调用时的环境中查.

  • 闭包的好处 关于闭包的好处可以看看下面这个例子.

    (define multi-delete
      (lambda (test-fun)
        (lambda (value lat)
          (cond
           ((null? lat) (quote ()))
           ((test-fun (car lat) value) ((multi-delete test-fun) value (cdr lat)))
           (else (cons (car lat) ((multi-delete test-fun) value (cdr lat))))
           ))))
    
    ((multi-delete =) 5 '(1 2 3 1 1 5 5 6 7))
    ((multi-delete >) 5 '(1 2 3 1 1 5 5 6 7))
    ((multi-delete <) 5 '(1 2 3 1 1 5 5 6 7))
    ((multi-delete (lambda (x y) (= x (+ y 2)))) 5 '(1 2 3 1 1 5 5 6 7))
    
    ;; => (1 2 3 1 1 6 7)
    ;; => (1 2 3 1 1 5 5)
    ;; => (5 5 6 7)
    

    以上函数用来从lat(纯数字list)中删除元素,实现了通用性很强的函数.multi-delete的删除过程 和删除条件分离.这样我们就可以复用multi-delete实现不同条件的删除.

  • again

    ;; 功能
    ;; 查询lat中的原子是否和a相等,如果相等则放入ls2,不相等则放入ls1.
    ;; 最后判断ls2是否为空.
    (define multirember&co
      (lambda (a lat col)
        (cond
         ((null? lat)
          (col (quote ()) (quote ())))
         ((eq? (car lat) a)
          (multirember&co a (cdr lat)
                          (lambda (newlat seen)
                            (col newlat
                                 (cons (car lat) seen)))))
         (else
          (multirember&co a (cdr lat)
                          (lambda (newlat seen)
                            (col (cons (car lat) newlat) seen)))))))
    (define a-friend
      (lambda (x y)
        (null? y)))
    

    为了便于理解,对以上代码做以下修改.

    (define multirember&co
      (lambda (a lat col)
        (begin
          (display col)
          (display "chen\n"))
        (cond
         ((null? lat)
          (col (quote ()) (quote ())))
         ((eq? (car lat) a)
          (multirember&co a (cdr lat)
                          (lambda (newlat seen)
                            (begin
                              (display newlat)
                              (display seen)
                              (display "\n")
                              (col newlat
                                   (cons (car lat) seen))))))
         (else
          (multirember&co a (cdr lat)
                          (lambda (newlat seen)
                            (begin
                              (display "<")
                              (display newlat)
                              (display seen)
                              (display ">\n")
                              (col (cons (car lat) newlat) seen))))))))
    
    (define a-friend
      (lambda (x y)
        (begin
          (display "[")
          (display x)
          (display y)
          (display "]\n"))))
    (multirember&co 'tuna '(strawberries tuna and swordifish) a-friend)
    ;;输出
    ;;#<procedure (a-friend x y)>chen
    ;;#<procedure (? newlat seen)>chen
    ;;#<procedure (? newlat seen)>chen
    ;;#<procedure (? newlat seen)>chen
    ;;#<procedure (? newlat seen)>chen
    ;;<()()>
    ;;<(swordifish)()>
    ;;(and swordifish)()
    ;;<(and swordifish)(tuna)>
    ;;[(strawberries and swordifish)(tuna)]
    ;;(multirember&co 'tuna '(strawberries tuna and swordifish) a-friend)
    

    lisp递归可以理解成不停地代换至终止条件,然后执行.通过display输出分析,multirember&co 调用了五次,其中第一次为a-friend函数,其余都为lambda表达式.其中lambda是一个闭包,依赖了 外部col参数,所以col为自由变量.参考闭包定义和词法作用域,"词法作用域的函数中遇到既不是 形参也不是函数内部定义的局部变量的变量时,去函数定义时的环境中查询".所以第一次定义 (lambda (newlat seen))时的col为,a-friend函数.第二次以及之后的(lambda (newlat seen)) 中的col同为(lambda (newlat seen)).

停机问题

发表于 2017-01-29 | 分类于 lisp |

1 停机问题

停机问题wiki 证明过程: 假设存在程序stop?满足以下要求: (stop? prog),如果prog停机返回#t否则返回#f. 定义不停机程序loop

(define loop
  (lambda() (loop)))

构造foo

(define foo
  (lambda()
    (and (stop? foo) (loop))))

使用(foo)调用foo程序,首先会对(stop? foo)表达式求值. 假设返回#f(foo不停机),根据and短路求值特性foo程序会直接返回#f从而结束程序(定义说明停机); 假设返回#t(foo停机),则会继续对(loop)求值,(loop)程序会一直运行(定义说明不停机). 两种case都产生矛盾,说明stop?程序不存在.

Android UI 库

发表于 2017-01-24 | 分类于 android |

1 android ui lib   PERSONAL

  • ui库
    1. TastyToast 炫酷的自定义toast.
    2. AdDialog 自定义的广告dialog.
    3. Onboarding A beautiful way to introduce users to your app.
    4. Android-SpinKit 加载动画库,配备各种加载动画.
    5. StickerView A view which can add sticker and zoom,drag,delete it.
    6. SlackLoadingView Slack loading animation.
    7. RecyclerRefreshLayout A pull to refresh layout for android, the RecyclerRefreshLayout is based on the SwipeRefreshLayout. support all the views, highly customizable, code simplicity, etc
    8. ViewPagerCards ViewPager cards.
    9. Fresco Facebook open source android picture lib.
    10. InstagramLikeColorTransitionAndroid How to create instagram like Gradient color transition in android.
    11. AnimShopButton A shopping cart button with a telescopic displacement rotation animation.
    12. ViewSpreadTranslationController View Spread TranslationController for Android.
    13. Android-SwitchIcon Google launcher-style implementation of switch (enable/disable) icon.
    14. PictureSelector Android多图选择器 图片/视频 单选or多选,以及视频录制.
    15. Toasty The usual Toast, but with steroids.
    16. Hover A floating menu library for Android.
  • 工具库
    1. Sharaku Image filtering UI library like Instagram.

用hexo搭建个人blog

发表于 2017-01-20 | 分类于 hexo |

1 hexo安装

以前陆陆续续用过csdn以及guthub pages写blog.始终没有坚持下来.近两年来一直在 学习eamcs.其中org-mode让我为之倾倒.在工作生活中也都有使用emacs.用过emacs群友 的org-page.但是界面不好看.最后还是放弃.直到遇到hexo和org-octopresss的组合.利 用org-mode进行写作,然后用org-octopress转化成html.搭配hexo的blog框架和漂亮的主 题.一切轻松简单.

关于hexo的介绍可以直接去看文档,开发者是一个台湾人.据说在高中时期就开发了hexo. hexo采用nodejs开发,安装过程和配置都比较简单.

npm install -g hexo-cli
hexo init <floder>
cd <floder>
npm install

hexo project根目录如下. tree.png _config.yml是hexo的站点配置文件,可以配置标题,地区,rss,部署以及评论等功能.

# Hexo Configuration
## Docs: http://hexo.io/docs/configuration.html
## Source: https://github.com/hexojs/hexo/

# Site
title: Flysands Blog
subtitle: Simple is the best
description: Keep life stayreal
author: Flysands
author_title: 'Programmer & Emacser'
avatar: css/images/mylogo.jpg
location: 'Chengdu, China'
follow: https://github.com/chenxs110/
language: zh-CN
timezone:
since: 2015 # The start year showing in your copyright section.

# URL
## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/'
url: http://chenxs110.github.com
# root: /
# permalink: :year/:month/:day/:title/
permalink: blog/:year-:month-:day-:title.html
permalink_defaults:

# Directory
source_dir: source
public_dir: public
tag_dir: tags
archive_dir: archives
category_dir: categories
code_dir: downloads/code
i18n_dir: :lang
skip_render:

# Writing
new_post_name: :title.md # File name of new posts
default_layout: post
titlecase: false # Transform title into titlecase
external_link: true # Open external links in new tab
filename_case: 0
render_drafts: false
post_asset_folder: false
relative_link: false
future: true
highlight:
  enable: true
  line_number: true
  tab_replace:

# Category & Tag
default_category: uncategorized
category_map:
tag_map:

# Date / Time format
## Hexo uses Moment.js to parse and display date
## You can customize the date format as defined in
## http://momentjs.com/docs/#/displaying/format/
date_format: YYYY-MM-DD
time_format: HH:mm:ss

# Pagination
## Set per_page to 0 to disable pagination
per_page: 6
pagination_dir: page

# Extensions
## Plugins: https://github.com/hexojs/hexo/wiki/Plugins
plugins:
  hexo-generator-feed
## Themes: https://github.com/hexojs/hexo/wiki/Themes
theme: icarus

# Disqus
# disqus_shortname: hexo-theme-icarus

# DuoShuo
duoshuo_shortname: flysands


# Deployment
## Docs: http://hexo.io/docs/deployment.html
deploy:
  type: git
  repository: http://github.com/chenxs110/chenxs110.github.io.git
  branch: master

2 配置主题

hexo的一大优点,就是有很多漂亮的主题.我选择了icarus.并配置了评论插件多说.

3 github pages搭建静态blog

可以参考github配置自己的blog.然后修改hexo站点中的deploy.注意要安装相应的deployer. 我用的是github.所以只需要安装git deployer即可.

# Deployment
## Docs: http://hexo.io/docs/deployment.html
deploy:
  type: git
  repository: http://github.com/chenxs110/chenxs110.github.io.git
  branch: master

安装deployer.

npm install hexo-deployer-git --save

如果需要开启rss订阅,需要安装generate-feed插件.

npm install hexo-generator-feed --save

并修改config.yml文件添加generate-feed插件.

plugins:
  hexo-generator-feed

在push到仓库之前,需要先执行hexo generate然后再执行hexo deploy进行部署.

4 emacs org-mode写blog

4.1 七牛云存储&hexo交互

写了几个简单函数用来做文件上传以及hexo交互.

(defun chenxuesong-qiniu-upload-img (command)
  (let ((command-str (format "~/Work/dev-tools/qiniu-devtools/qrsync %s"
                             command)))
    (shell-command-to-string command-str)))

(defun chenxuesong-qiniu-achieve-image ()
  (shell-command-to-string "cp -rf ~/Work/blog/images/* ~/Work/blog/images-achieve")
  (shell-command-to-string "rm -f ~/Work/blog/images/*"))

(defun chenxuesong-hexo-generate (args)
  (interactive "P")
  (let ((default-directory chenxueosng-blog-dir))
    (shell-command-to-string "hexo generate")
    (message "hexo generate complete.")))

(defun chenxuesong-hexo-deploy (args)
  (interactive "P")
  (let ((default-directory chenxueosng-blog-dir))
    (chenxuesong-qiniu-upload-img (concat chenxueosng-blog-dir "qiniu.json"))
    (shell-command-to-string "hexo deploy")
    (chenxuesong-qiniu-achieve-image)
    (message "hexo deploy complete.")))

(defun chenxuesong-insert-qiniu-link (imagename)
  (interactive "sImage name: ")
  (insert (concat (format "[[%s%s]]" "http://7xia6k.com1.z0.glb.clouddn.com/"
                          imagename))))

4.2 org-octopress

org-octopress原本是用来把org转化成适合octopress的html文件.由于hexo兼容 octopress.所以也可以用来生成适用于hexo的html文件. 配置如下:

(setq org-blog-dir "~/Work/blog/")
(setq org-octopress-directory-top org-blog-dir)
(setq org-octopress-directory-posts (concat org-blog-dir "source/_posts"))
(setq org-octopress-directory-org-top org-blog-dir)
(setq org-octopress-directory-org-posts (concat org-blog-dir "blog"))
(setq org-octopress-setup-file (concat org-blog-dir "setupfile.org"))

注意org-posts文件夹不能放到source文件中.否则会生成失败.

4.3 快捷键

添加了几个用于发布和转换html的快捷键.

(evil-leader/set-key "oc" 'chenxuesong/org-create-org-blog-file)
(evil-leader/set-key "op" 'chenxuesong/org-save-and-export)
(evil-leader/set-key "od" 'chenxuesong-hexo-deploy)
(evil-leader/set-key "og" 'chenxuesong-hexo-generate)

(defun chenxuesong-qiniu-upload-img (command)
  (let ((command-str (format "~/Work/dev-tools/qiniu-devtools/qrsync %s"
                             command)))
    (shell-command-to-string command-str)))

(defun chenxuesong-qiniu-achieve-image ()
  (shell-command-to-string "cp -rf ~/Work/blog/images/* ~/Work/blog/images-achieve")
  (shell-command-to-string "rm -f ~/Work/blog/images/*"))

(defun chenxuesong-hexo-generate (args)
  (interactive "P")
  (let ((default-directory chenxueosng-blog-dir))
    (shell-command-to-string "hexo generate")
    (message "hexo generate complete.")))

(defun chenxuesong-hexo-deploy (args)
  (interactive "P")
  (let ((default-directory chenxueosng-blog-dir))
    (chenxuesong-qiniu-upload-img (concat chenxueosng-blog-dir "qiniu.json"))
    (shell-command-to-string "hexo deploy")
    (message "hexo deploy complete.")))

react-native开发跨平台应用

发表于 2017-01-20 | 分类于 react |

1 react-native背景

React Native 结合了 Web 应用和 Native 应用的优势,可以使用 JavaScript 来开发 iOS 和 Android 原生应.在 JavaScript 中用 React 抽象操作系统原生的 UI 组件, 代替 DOM 元素来渲染等.

React Native 使你能够使用基于 JavaScript 和 React 一致的开发体验在本地平台 上构建世界一流的应用程序体验.React Native 把重点放在所有开发人员关心的平台 的开发效率上.所以开发者只需学习一种语言就能轻易为任何平台高效地编写代码.

2 安装工具集

requirement version
xcode ios 7以上
android android build tool 23.0.1以上
nodejs 4.0以上
react-native 0.1.7

我的机器是osx,所以整个安装过程都用brew进行.安装之前建议先更新一下brew.

brew update
brew upgrade
  • 安装nodejs

    mac用户直接去官网下载pkg文件安装.注意nodejs版本要高于4.0.

  • 安装watchman

    brew install watchman
    
  • 安装flow

    brew install flow
    
  • 安装react-native

    npm install -g react-native-cli
    

3 第一个跨平台应用

创建过程可以参考帮助文档1. 所有工具集安装完毕后,创建第一个project吧.

react-native init your-project-dir

project创建成功后会生成ios和android的project目录,以及两个平台的index入口js 文件.

  • run android device

    cd your-project
    react-native run-android
    

    查看日志

    adb logcat *:S ReactNative:V ReactNativeJS:V
    

    启动成功 react-native.png

  • run ios 打开ios目录中的xcodeproj文件.点击run按钮即可.

4 使用组件

react-native提供了丰富的native组件.

var React = require('react-native');
var {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  TextInput,// add text input component
} = React;


var TestProject = React.createClass({
  render: function() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          Welcome to React Native!
        </Text>
        <Text style={styles.instructions}>
          To get started, edit index.android.js
        </Text>
        <Text style={styles.instructions}>
          Shake or press menu button for dev menu
        </Text>
        // add text input
        <TextInput
        style={{height: 40, borderColor: 'gray', borderWidth: 1}}
        onChangeText={(text) => this.setState({text})}
        />
      </View>
    );
  }
});

react-native-input.png

5 问题

  1. 安装react-native报警

    如果用nvm管理多个node版本.并且安装提示node版本过低.重新下载pkg安装包.安装

即可.

  1. run-android报错

    react-native android打包工具要23.0.1以上的版本.解决方法是在sdk manager中

安装高版本android build tool.

  1. 启动报错

    stackoverflow2上有讨论,我在模拟器上执行adb reverse命令做端口映射即可.

    adb reverse tcp:8081 tcp:8081
    

6 总结

总的来说开发方式还是便捷许多.但是存在一个普遍问题.跨平台应用开发的通病-性能.

Footnotes:

1

react-native doc https://facebook.github.io/react-native/docs/getting-started.html

2

stackoverflow http://stackoverflow.com/questions/32572399/react-native-android-failed-to-load-js-bundle

android指纹模块

发表于 2017-01-20 | 分类于 android |

Table of Contents

  • 1. android指纹模块流程图
  • 2. android setting指纹模块入口
  • 3. nexus 6p无法启用finger问题原因

1 android指纹模块流程图

android_finger_module_seq.png

  • Tee : trusted excution env

2 android setting指纹模块入口

主要涉及到一下几个文件

  • packages/apps/Settings/src/com/android/settings/SecuritySettings.java
  • frameworks/base/core/java/android/hardware/fingerprint/FingerprintManager.java
  • frameworks/base/services/core/java/com/android/server/fingerprint/FingerprintService.java
  • frameworks/base/core/java/android/hardware/fingerprint/IFingerprintDaemon.aidl
  • system/core/fingerprintd/IFingerprintDaemon.cpp
  • system/core/fingerprintd/FingerprintDaemonProxy.cpp
  • hardware/libhardware/hardware.c
  • hardware/libhardware/modules/fingerprint/fingerprint.c

android_finger_setting_load.png

具体流程如下:

  1. Settings在做页面展示的时候会调用maybeAddFingerprintPreference函数判断是否 添加fingerprint preference.
  2. maybeAddFingerprintPreference内部调用FingerprintManager的isHardwareDetected 函数.
  3. FingerprintManager调用FingerprintService中的isHardwareDetected函数.
  4. FingerprintService中的isHardwareDetected函数首先进行权限检查,然后如果 mDeviceHalId等于0返回false,表示没有检测到指纹相关的硬件.否则返回ture. mDeviceHalId为底层openHal的返回值.
  5. openHal函数的实现非常简单,代码片段如下.

    int64_t FingerprintDaemonProxy::openHal() {
      ALOG(LOG_VERBOSE, LOG_TAG, "nativeOpenHal()\n");
      int err;
      const hw_module_t *hw_module = NULL;
      if (0 != (err = hw_get_module(FINGERPRINT_HARDWARE_MODULE_ID, &hw_module))) {
        ALOGE("Can't open fingerprint HW Module, error: %d", err);
        return 0;
      }
      if (NULL == hw_module) {
        ALOGE("No valid fingerprint module");
        return 0;
      }
    
      mModule = reinterpret_cast<const fingerprint_module_t *>(hw_module);
    
      if (mModule->common.methods->open == NULL) {
        ALOGE("No valid open method");
        return 0;
      }
    
      hw_device_t *device = NULL;
    
      if (0 != (err = mModule->common.methods->open(hw_module, NULL, &device))) {
        ALOGE("Can't open fingerprint methods, error: %d", err);
        return 0;
      }
    
      if (kVersion != device->version) {
        ALOGE("Wrong fp version. Expected %d, got %d", kVersion, device->version);
        // return 0; // FIXME
      }
    
      mDevice = reinterpret_cast<fingerprint_device_t *>(device);
      err = mDevice->set_notify(mDevice, hal_notify_callback);
      if (err < 0) {
        ALOGE("Failed in call to set_notify(), err=%d", err);
        return 0;
      }
    
      // Sanity check - remove
      if (mDevice->notify != hal_notify_callback) {
        ALOGE("NOTIFY not set properly: %p != %p", mDevice->notify,
              hal_notify_callback);
      }
    
      ALOG(LOG_VERBOSE, LOG_TAG, "fingerprint HAL successfully initialized");
      return reinterpret_cast<int64_t>(mDevice); // This is just a handle
    }
    

    openHal函数主要实现以下3个功能

    • 调用hw_get_module加载对应的库文件
    • 调用module结构体的common.methods->open指向的函数 module结构体定义如下

      static struct hw_module_methods_t fingerprint_module_methods = {
          .open = fingerprint_open,
      };
      
      fingerprint_module_t HAL_MODULE_INFO_SYM = {
          .common =
              {
                  .tag = HARDWARE_MODULE_TAG,
                  .module_api_version = FINGERPRINT_MODULE_API_VERSION_2_0,
                  .hal_api_version = HARDWARE_HAL_API_VERSION,
                  .id = FINGERPRINT_HARDWARE_MODULE_ID,
                  .name = "Emulator Fingerprint HAL",
                  .author = "The Android Open Source Project",
                  .methods = &fingerprint_module_methods,
              },
      };
      

      fingerprint_open函数定义如下

      static int fingerprint_open(const hw_module_t *module, const char __unused *id,
                                  hw_device_t **device) {
        if (device == NULL) {
          ALOGE("NULL device on open");
          return -EINVAL;
        }
      
        fingerprint_device_t *dev = malloc(sizeof(fingerprint_device_t));
        memset(dev, 0, sizeof(fingerprint_device_t));
      
        dev->common.tag = HARDWARE_DEVICE_TAG;
        dev->common.version = FINGERPRINT_MODULE_API_VERSION_2_0;
        dev->common.module = (struct hw_module_t *)module;
        dev->common.close = fingerprint_close;
      
        dev->pre_enroll = fingerprint_pre_enroll;
        dev->enroll = fingerprint_enroll;
        dev->get_authenticator_id = fingerprint_get_auth_id;
        dev->cancel = fingerprint_cancel;
        dev->remove = fingerprint_remove;
        dev->set_active_group = fingerprint_set_active_group;
        dev->authenticate = fingerprint_authenticate;
        dev->set_notify = set_notify_callback;
        dev->notify = NULL;
      
        *device = (hw_device_t *)dev;
        return 0;
      }
      
    • 调用set_notify设置回调函数
  6. hw_get_module函数主要实现底层so库加载 具体加载过程可以参考android hw_get_module 分析
  7. hw_get_module内部调用hw_get_module_by_class实现加载过程

    /** Base path of the hal modules */
    #if defined(__LP64__)
    #define HAL_LIBRARY_PATH1 "/system/lib64/hw"
    #define HAL_LIBRARY_PATH2 "/vendor/lib64/hw"
    #else
    #define HAL_LIBRARY_PATH1 "/system/lib/hw"
    #define HAL_LIBRARY_PATH2 "/vendor/lib/hw"
    #endif
    
    /**
     * There are a set of variant filename for modules. The form of the filename
     * is "<MODULE_ID>.variant.so" so for the led module the Dream variants
     * of base "ro.product.board", "ro.board.platform" and "ro.arch" would be:
     *
     * led.trout.so
     * led.msm7k.so
     * led.ARMV6.so
     * led.default.so
     */
    
    static const char *variant_keys[] = {
        "ro.hardware", /* This goes first so that it can pick up a different
                          file on the emulator. */
        "ro.product.board",
        "ro.board.platform",
        "ro.arch"};
    

    hw_get_module_by_class根据优先级搜索对应的so文件,文件名主要由两部分构成. 第一部分为模块名,第二部分为类型.其中模块名固定,第二部分优先级顺序为: 硬件 > 产品 > cpu > arch > default.

    如果以上函数都执行成功,那么fingerprint module则加载完成.

3 nexus 6p无法启用finger问题原因

  1. 清华镜像的源码选择angler product,编译出来的system.img里没有fingerprintd可执行文件.
  2. 没有加载fingerprint module对应的库文件.
  3. hardware so库加载顺序有误.
  4. 解决方法 以移植goldfish为例
    1. 拷贝device/generic/goldfish/fingerprint目录到device/huawei/angler目录下
    2. 修改device/huawei/angler/device.mk文件,添加fingerprint模块

      #Fingerprint
      PRODUCT_PACKAGES += \
                       fingerprintd \
                       fingerprint.msm8994
      
    3. 修改模块加载顺序 由于源码编译出来的image文件,在system/vendor/lib64下含有fingerprint.angler.so. 所以在hw_get_module会加载fingerprint.angler.so而忽略fingerprint.msm8994.so. 所以修改hardware.c文件中的默认搜索顺序,把ro.board.platform放到第一即可.

      static const char *variant_keys[] = {
          "ro.board.platform",
          "ro.hardware", /* This goes first so that it can pick up a different
                            file on the emulator. */
          "ro.product.board",
          // "ro.board.platform",
          "ro.arch"};
      
123
Flysands

Flysands

Keep life stayreal

16 日志
9 分类
14 标签
GitHub E-Mail 微博
© 2016 — 2017 Flysands
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.3