点击打开链接

文档目的

在Android手机生产过程中,有时需要做一些器件测试或者其他压力测试,并且保存测试结果,即使手机恢复出场设置或者重新下载版本也不会擦出这些结果,这个时候就要用到NV来保存。本文主要介绍高通平台上层通过调用jni层方法保存NV和读取NV的方法。

java层方法定义

使用高通的工具QXDM连接手机,用NV Browser查看手机的NV数据:
接下来以NVID[02497] Factory Data Storage Area 1为例。
新建一个java文件: NvWriter.java
[java] view plaincopy
  1. public class NvWriter {
  2. private static final String TAG = "NvWriter-TAG";
  3. private static NvWriter sInstance = null;
  4. /*FLAG RESULT*/
  5. public static final char PASS = 'P';
  6. public static final char FAIL = 'F';
  7. public static final char NA = ' ';
  8. static {
  9. System.loadLibrary("nvwriter_jni");
  10. }
  11. private native String native_readflag_NV();
  12. private native void native_writeflag_NV(int index,char result);
  13. public static NvWriter getInstance() {
  14. if (sInstance == null) {
  15. sInstance = new NvWriter();
  16. }
  17. return sInstance;
  18. }
  19. public String readFlagNV() {
  20. String mFlagNv = native_readflag_NV();
  21. Log.i(TAG,"readFlagNV: mFlagNv = " + mFlagNv);
  22. return mFlagNv;
  23. }
  24. public void writeFlagNV(int index,char result) {
  25. native_writeflag_NV(index,result);
  26. }
  27. public char getFlag(int index) {
  28. String mFlagNv = readFlagNV();
  29. char flag = NA;
  30. if (mFlagNv != null && mFlagNv.length() >= index) {
  31. flag = mFlagNv.charAt(index);
  32. }
  33. Log.i(TAG,index + ": flag = " + flag);
  34. return flag;
  35. }
  36. }
这个类中只有几个简单的方法:
1.一个单实例的构造方法
2.3个public的操作NV的java方法
3.2个native方法
这样我们在需要操作NV的地方,可以像下面这样:
1.写NV:
[java] view plaincopy
  1. NvWriter.getInstance().writeFlagNV(index,NvWriter.PASS);

2.读取NV:

[java] view plaincopy
  1. NvWriter.getInstance().getFlag(index);

上述方法具体实现都是在jni层,我们接下来看一下jni层是如何实现的。

Jni层方法实现

新建一个cpp文件nvwriter.cpp:
[cpp] view plaincopy
  1. #include <unistd.h>
  2. #include <utils/Log.h>
  3. #include <cutils/log.h>
  4. #include <jni.h>
  5. #include <JNIHelp.h>
  6. #include <stdlib.h>
  7. #include "android_runtime/AndroidRuntime.h"
  8. #include <android/log.h>
  9. #include "nv.h"
  10. #ifdef LOG_TAG
  11. #undef LOG_TAG
  12. #endif
  13. #define LOG_TAG "NVWriter-TAG-JNI"
  14. #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
  15. static int SHOW_LOG = 1; // 1 for show log.
  16. static int SHOW_NV_LOG = 0; // 1 for show log.
  17. static const char* const className = "com/xxx/nv/NvWriter";
  18. jint NativeInit() {
  19. /* Calling LSM init  */
  20. if(!Diag_LSM_Init(NULL)) { // 调用diag初始化
  21. LOGI("Diag_LSM_Init() failed.");
  22. return -1;
  23. }
  24. LOGI("Diag_LSM_Init succeeded. \n");
  25. /* Register the callback for the primary processor */
  26. register_callback();  // 注册回调方法
  27. return 1;
  28. }
  29. jstring CharTojstring(JNIEnv* env,const char* str) { // char转化为jstring
  30. jsize len = strlen(str);
  31. jclass clsstring = env->FindClass("java/lang/String");
  32. jstring strencode = env->NewStringUTF("utf-8");
  33. jmethodID mid = env->GetMethodID(clsstring,"<init>","([BLjava/lang/String;)V");
  34. jbyteArray barr = env->NewByteArray(len);
  35. env->SetByteArrayRegion(barr,0,len,(jbyte*)str);
  36. return (jstring)env->NewObject(clsstring,mid,barr,strencode);
  37. }
  38. void android_native_writeflag_NV(JNIEnv *env,jobject this_,jint index,jchar result) { //先读后存
  39. if (SHOW_LOG) {
  40. LOGI("android_native_writeflag_NV");
  41. }
  42. if (NativeInit() < 0) {  // 若初始化不成功则直接返回
  43. return;
  44. }
  45. unsigned char tmp[22] = { 0 };
  46. unsigned char after[20] = { 0 };
  47. nv_items_enum_type nvId = NV_FACTORY_DATA_3_I; // 我们要操作的NVID
  48. memset(tmp, 0, sizeof(tmp));   // 申请mem
  49. memset(after, 0, sizeof(after));
  50. diag_nv_read(nvId,tmp, sizeof(tmp));  // 调用高通操作nv的api,读取NV给tmp
  51. for(int m=0;m < sizeof(tmp)-3;m++) {  // 去掉tmp的前三个字段,重新赋值给after
  52. if (tmp[m+3] == NULL) {
  53. after[m] = ' ';
  54. } else {
  55. after[m] = tmp[m+3];
  56. }
  57. }
  58. LOGI("android_native_writeflag_NV index = %d\n",(int)index);
  59. after[sizeof(tmp)-3+1] = '\0';
  60. after[index] = result;  // 把我们要操作的某一位重新赋值
  61. if (SHOW_NV_LOG) {
  62. for (int n=0;n < sizeof(after);n++) {
  63. LOGI("android_native_writeflag_NV,after[%d] = %02x \n",n,after[n]);
  64. }
  65. }
  66. diag_nv_write(nvId,after, sizeof(after));  // 调用高通写nv的api,重新写nv
  67. }
  68. jstring android_native_readflag_NV(JNIEnv *env) { // 读取nv
  69. if (SHOW_LOG) {
  70. LOGI("android_native_readflag_NV");
  71. }
  72. if (NativeInit() < 0) { // 若初始化不成功则直接返回
  73. return NULL;
  74. }
  75. unsigned char tmp[23] = { 0 };
  76. unsigned char after[21] = { 0 };
  77. memset(tmp, 0, sizeof(tmp));
  78. memset(after, 0, sizeof(after));
  79. nv_items_enum_type nvId = NV_FACTORY_DATA_3_I;
  80. diag_nv_read(nvId,tmp, sizeof(tmp));  // 调用高通操作nv的api,读取NV给tmp
  81. for(int m=0;m < sizeof(tmp)-3;m++) {  // 去掉tmp的前三个字段,重新赋值给after
  82. if (tmp[m+3] == NULL) {
  83. after[m] = ' ';
  84. } else {
  85. after[m] = tmp[m+3];
  86. }
  87. }
  88. after[sizeof(tmp)-3+1] = '\0';
  89. const char* p = (const char*)(char*)after;
  90. if (SHOW_NV_LOG) {
  91. for(int i=0;i < sizeof(after);i++) {
  92. LOGI("android_native_readflag_NV p[%d] = %02x\n",i,p[i]);
  93. }
  94. }
  95. jstring flag_string = CharTojstring(env,p);  // char转化为jstring
  96. return flag_string;
  97. }
  98. JNINativeMethod gMethods[] = {
  99. { "native_writeflag_NV", "(IC)V",(void*) android_native_writeflag_NV },
  100. { "native_readflag_NV", "()Ljava/lang/String;",(void*) android_native_readflag_NV }
  101. };
  102. int registerNativeMethods(JNIEnv* env) { //注册方法
  103. jclass clazz;
  104. clazz = env->FindClass(className);
  105. if (env->RegisterNatives(clazz, gMethods,
  106. sizeof(gMethods) / sizeof(gMethods[0])) < 0) {
  107. return -1;
  108. }
  109. return 0;
  110. }
  111. jint JNI_OnLoad(JavaVM* vm, void* reserved) {
  112. JNIEnv* env = NULL;
  113. jint result = -1;
  114. if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) == JNI_OK) {
  115. if (NULL != env && registerNativeMethods(env) == 0) {
  116. result = JNI_VERSION_1_4;
  117. }
  118. }
  119. return result;
  120. }

这个cpp要做的事情主要有以下几点:

1.注册JNI方法
2.调用高通平台自带的操作nv的方法进行读取和写NV
3.处理返回的值并传递给java层
有三点需要注意:
1.diag_nv_read读取返回的nv值前三位要去掉
2.返回的char要转化为jstring才能传递给上层
3.nv操作必须要先调用Diag_LSM_Init(NULL)初始化,并register_callback();
总结一下:
由于高通平台自带的源码中就有操作NV的函数,但是是位于cpp中的(vendor/qcom/proprietary/fastmmi和vendor/qcom/proprietary/diag中),但是我们自己的java文件无法直接调用高通的cpp文件,所以我们需要写一个jni文件进行中转。
即:我们的java->我们的jni->高通的cpp
最终实现我们的需求。
最后再注:
在jni文件对应的Android.mk中要加入以下语句,不然会编译报错:
[plain] view plaincopy
  1. LOCAL_C_INCLUDES += \
  2. vendor/qcom/proprietary/fastmmi/libmmi \
  3. external/libcxx/include \
  4. external/skia/include/core \
  5. external/libxml2/include \
  6. external/icu/icu4c/source/common \
  7. $(QC_PROP_ROOT)/diag/include \
  8. $(QC_PROP_ROOT)/diag/src/ \
  9. $(TARGET_OUT_HEADERS)/common/inc
  10. LOCAL_SHARED_LIBRARIES := \
  11. libutils \
  12. libcutils \
  13. libc \
  14. libmmi \
  15. libdiag

高通平台java层操作NV数据的方法相关推荐

  1. 高通平台wifi命令操作

    请先打patch,再烧录打patch之后编译的镜像,将xbin.zip里的工具通过adb push到system/xbin目录下,并更改权限(也可以把这几个文件放在代码里,在编译时copy到syste ...

  2. 华为鸿蒙或适配高通平台,博主简评华为鸿蒙操作系统,亮点是分布式操作,或将适配高通平台...

    原标题:博主简评华为鸿蒙操作系统,亮点是分布式操作,或将适配高通平台 博主简评华为鸿蒙操作系统,亮点是分布式操作,或将适配高通平台 鸿蒙OS 2.0操作系统究竟如何?到底多久后才能正式推送?知名大V博 ...

  3. 高通平台android开发总结

    http://www.cnblogs.com/yuzaipiaofei/archive/2012/07/24/4124179.html 1.高通平台android开发总结 1.1 搭建高通平台环境开发 ...

  4. 高通平台android 环境配置编译及开发经验总结

    完全转自:http://blog.csdn.net/dongwuming/article/details/12784535 1.高通平台android开发总结 1.1 搭建高通平台环境开发环境 在高通 ...

  5. 高通平台android开发总结 .

    http://blog.csdn.net/mirkerson/article/details/7691029 http://blog.csdn.net/mirkerson/article/detail ...

  6. 高通平台android 环境配置编译及开发经验总结【转】

    1.高通平台android开发总结 1.1 搭建高通平台环境开发环境 在高通开发板上烧录文件系统 建立高通平台开发环境 高通平台,android和 modem 编译流程分析 高通平台 7620 启动流 ...

  7. 高通平台lcm 总结

    以下几幅图是最近的一段时间对自己模块LCM的一些总结,目前只是完成了一部分,而且描述的不是特别到位,后期会不断更新和修改的. 第一幅是LCM的总体移植框架和组件图.介绍了LCM驱动的分部和调试屏的步骤 ...

  8. 高通平台android7.1系统显示旋转180度

    实现方法 内核层修改 kernel\msm-3.18\arch\arm\boot\dts\qcom\dsi-panel-lm215w-lvds-1080p-video.dtsi增加qcom,mdss- ...

  9. 高通平台sensor学习

    刚入行驱动时最先接触调试的外设模块便是sensor,一直都是零零散散的记录,这次终于下定决心对自己所学做一个系统的总结. sensor作为一款常用的外设,虽不起眼但是很多功能确实离不开它.比如我们手机 ...

最新文章

  1. 报名 | DeeCamp2019:实战AI 铸造定雨神针
  2. 全志A33-修改linux kernel启动参数
  3. win7禁用Adnimistrator账号登录
  4. linux镜像包含数据库数据么,docker 镜像中包含数据库环境和运行环境
  5. linux ftp验证指令,linux FTP常用指令说明
  6. 如何把MySql数据库中的数据导入到MyCat集群中_---Linux运维工作笔记050
  7. div设置高度 vue_VsCode常用设置(新手必备!)
  8. Zabbix监控Nginx连接状态
  9. ResNet----残差结构
  10. MFC 对话框 添加 工具栏
  11. HTTP报文字段说明
  12. Sketch79 mac专业矢量绘图设计
  13. echarts地图各种点位实现
  14. Eterm连接不上-10001:登录失败
  15. 完美:利用旧版iCloud更改Apple ID地区
  16. c语言中swipe的作用,浅谈在vue中使用mint-ui swipe遇到的问题
  17. liunx安装jdk报A fatal exception has occurred. Program will exit
  18. DNS劫持、流量劫持,HTTP/HTTPS劫持
  19. use SWR为什么能成为我的最爱React库?
  20. QQ邮箱不显示图片解决方案

热门文章

  1. Java JVM内存模型
  2. 004_Mysql数据库的CRUD的操作
  3. mysql memory_MySQL MEMORY 引擎及性能比对
  4. linux链接curl库,Linux利用curl库快速开发http应用
  5. Android Studio系列教程一:下载与安装
  6. html 背景设为透明背景图片,Three.js中通过透明渲染设置默认背景图片
  7. bapi sap 创建物料_SAP使用BAPI创建物料主数据的最小输入-阿里云开发者社区
  8. python structure_GitHub - CYZYZG/Data_Structure_with_Python: 这是我在学习《基于Python的数据结构》的时候的笔记与代码...
  9. 华为云计算之ebackup了解
  10. kindeditor java 上传图片_java中KindEditor本地图片上传与上传失败问题