在做项目过程中客户提了定制化需求:即保存一段数据,即使在设备恢复出厂的情况下,数据亦不能删除。
参考了一些资料,由于大版本不同,在之前的版本上做了对应的修改。
- 添加 nvram lib数据结构定义
vendor/mediatek/proprietary/custom/myproject/cgen/cfgfileinc/CFG_Custom1_File.h
+typedef struct
+{
+ unsigned char Array[1024];
+}File_My_Custom1_Struct;
+
+#define CFG_MY_CUSTOM1_REC_SIZE sizeof(File_MY_CUSTOM1_Struct)
+#define CFG_MY_CUSTOM1_REC_TOTAL 1
- 添加nvram lib默认值定义
vendor/mediatek/proprietary/custom/myproject/cgen/cfgdefault/CFG_Custom1_Default.h
+File_My_Custom1_Struct stMyCustom1Default =
+{
+
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
+};
- 添加nvram lib id定义
vendor/mediatek/proprietary/custom/myproject/cgen/inc/Custom_NvRam_LID.h
AP_CFG_RDCL_FILE_AUDIO_BT_GAIN_CUSTOM_LID,
AP_CFG_RDCL_FILE_AUDIO_FUNC_SWITCH_PARAM_LID,
AP_CFG_CUSTOM_FILE_FUEL_GAUGE_LID,
+ AP_CFG_CUSTOM_FILE_MY_CUSTOM1_LID,
AP_CFG_CUSTOM_FILE_MAX_LID,
} CUSTOM_CFG_FILE_LID;
+#define AP_CFG_CUSTOM_FILE_MY_CUSTOM1_LID_VERNO "000"
- 添加nvram lib id的数据结构
vendor/mediatek/proprietary/custom/myproject/cgen/inc/Custom_NvRam_data_item.h
+LID_BIT VER_LID(AP_CFG_CUSTOM_FILE_MY_CUSTOM1_LID)
+File_My_Custom1_Struct *CFG_MY_CUSTOM1_REC_TOTAL
+{
+
+};
- nvram lib数据加入到nvram数组中(切记加到数组末尾)
vendor/mediatek/proprietary/custom/myproject/cgen/inc/CFG_file_info_custom.h
const TCFG_FILE g_akCFG_File_Custom[]=
{
...
+ { "/mnt/vendor/protect_f/MY_CUSTOM1", VER(AP_CFG_CUSTOM_FILE_MY_CUSTOM1_LID), CFG_MY_CUSTOM1_REC_SIZE,
+ CFG_MY_CUSTOM1_REC_TOTAL, SIGNLE_DEFUALT_REC, (char *)&stMyCustom1Default, DataReset , NULL
+ },
};
目前nvram lib id添加已基本完成,下一步需要对nvram数据进行读写操作。现在做法是对读写进行类封装,做成jar包供应用调用。
vendor\mediatek\proprietary\packages\apps\MtkSettings\src\com\mediatek\settings\test\MyCustom1Manager.java
package com.mediatek.settings.test;
import static android.net.wifi.ScanResult.InformationElement;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.IBinder ;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Log;
import com.android.internal.util.HexDump;
import java.lang.InterruptedException;
import java.lang.Thread;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.StringTokenizer;
import vendor.mediatek.hardware.nvram.V1_0.INvram;
public class MyCustom1Manager {
private static final String TAG = "MyCustom1Manager";
private static final int MY_CUSTOM1_SIZE = 18;
///backup/APCFG/APRDEB/MY_CUSTOMS1
///mnt/vendor/nvdata/APCFG/APRDEB/
///vendor/nvdata/APCFG/APRDEB
///data/nvram/APCFG/APRDEB
///vendor/nvdata/md/NVRAM/
///mnt/vendor/protect_f/
private static final String MY_CUSTOM1_FILENAME = "/mnt/vendor/protect_f/MY_CUSTOM1";
public String getMyCustom1FromNvram() {
try {
int i = 0;
String buff = null;
INvram agent = null;
try {
agent = INvram.getService();
} catch (NoSuchElementException ne) {
ne.printStackTrace();
}
if (agent == null) {
Log.e(TAG, "NvRAMAgent is null");
try {
Thread.sleep(100);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
//try get agent
agent = INvram.getService();
}
if (agent == null) {
Log.e(TAG, "No support My Custom1 writing due to NVRAM");
Log.e(TAG, "NvRAMAgent is null");
return "";
}
try {
buff = agent.readFileByName(
MY_CUSTOM1_FILENAME, MY_CUSTOM1_SIZE);
} catch (Exception e) {
e.printStackTrace();
return "";
}
Log.i(TAG, "Raw data:" + buff);
return hexToString(buff).trim();
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "getMyCustom1FromNvram exception:" + e.getMessage());
return "";
}
}
public String hexToString(String hex) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hex.length() - 1; i += 2) {
int decimalValue = Integer.parseInt(hex.substring(i, i + 2), 16);
// 添加到结果字符串中
sb.append((char) decimalValue);
}
return sb.toString();
}
public byte[] hexStringToByteArray(String hexString) {
if (hexString == null || hexString.length() == 0) return new byte[0];
int len = hexString.length();
byte[] byteArray = new byte[len / 2];
for ( int start = 0; start < len - 1; start += 2 )
{
String thisByte = hexString.substring(start, start+2);
byteArray[start/2] = Byte.parseByte(thisByte, 16);
}
return byteArray;
}
public boolean updateMyCustom1(String data) {
try {
INvram agent = null;
try {
agent = INvram.getService();
} catch (NoSuchElementException ne) {
ne.printStackTrace();
}
if (agent == null) {
Log.e(TAG, "NvRAMAgent is null");
try {
Thread.sleep(100);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
//try get agent
agent = INvram.getService();
}
if (agent == null) {
Log.e(TAG, "No support My Custom1 writing due to NVRAM");
Log.e(TAG, "NvRAMAgent is null");
return false;
}
String buff = null;
try {
buff = agent.readFileByName(
MY_CUSTOM1_FILENAME, MY_CUSTOM1_SIZE);
} catch (Exception e) {
e.printStackTrace();
return false;
}
if (buff.equals(data)) return true;
//byte[] buffArr = HexDump.hexStringToByteArray(buff.substring(0, buff.length() - 1));
byte[] buffArr = hexStringToByteArray(buff);
byte[] dataArr = data.getBytes();
int i = 0,j = 0;
int len = dataArr.length;
Log.e(TAG, "dataArr length:" + len);
ArrayList<Byte> dataArray = new ArrayList<Byte>(
MY_CUSTOM1_SIZE);
for (i = 0, j = 0; i < MY_CUSTOM1_SIZE; i++) {
if (MY_CUSTOM1_SIZE - i > len) {
if (i < buffArr.length) {
dataArray.add(buffArr[i]);
} else {
dataArray.add((byte)0x00);
}
} else {
dataArray.add(dataArr[j]);
if (j < len) {
j++;
}
}
}
int flag = 0;
try {
Log.e(TAG, "writeFileByNamevec dataArray:" + dataArray.toString());
flag = agent.writeFileByNamevec(MY_CUSTOM1_FILENAME,
MY_CUSTOM1_SIZE, dataArray);
} catch (Exception e) {
Log.e(TAG, "writeFileByNamevec error:" + e.getMessage());
return false;
}
} catch (Exception e) {
Log.e(TAG, "updateMyCustom1 error:" + e.getMessage());
}
return true;
}
}
因为 import vendor.mediatek.hardware.nvram.V1_0.INvram; 在应用中无法导入,怎么生成jar包呢,… ,可以借助系统模块编译生成(灵光一现),下面是jar包生成方法
vendor\mediatek\proprietary\packages\apps\MtkSettings\MyCustom1.mf
Main-Class: com.mediatek.settings.test.MyCustom1Manager
vendor/mediatek/proprietary/packages/apps/MtkSettings/Android.bp
+java_library {
+ name: "MyCustom1Manager",
+ srcs: ["src/com/mediatek/settings/test/MyCustom1Manager.java",],
+ manifest: "MyCustom1.mf",
+ platform_apis: true,
+ static_libs: [
+ "vendor.mediatek.hardware.nvram-V1.0-java"
+ ],
+ libs: [
+ "framework",
+ ]
}
android_library {
name: "MtkSettings-core",
...
static_libs: [
...
"android.hardware.dumpstate-V1.1-java",
"lottie",
+ "vendor.mediatek.hardware.nvram-V1.0-java"
],
...
}
编译类和编译资源已添加完成,然后使用如下指令进行编译:
mmma vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/mediatek/settings/test/
编译完成后jar包会生成在out目录下,路径为:
out\soong.intermediates\vendor\mediatek\proprietary\packages\apps\MtkSettings\MyCustom1Manager\android_common\combined\MyCustom1Manager.jar
生成后添加到项目中直接实例化调用即可。
最后,使用时可能会遇到selinux权限问题,可以尝试进行如下添加:
+allow mtk_hal_nvramagent protect_f_data_file:dir {search write add_name};
+allow mtk_hal_nvramagent protect_f_data_file:file {create open read write getattr setattr};
+allow mtk_hal_nvramagent sysfs_dt_firmware_android:dir {search};
+allow mtk_hal_nvramagent sysfs_dt_firmware_android:file {read getattr open write};
以上就是nvram数据保存的全部修改,如有不对欢迎指正。