android12 无法写入NV分区 报错。
2025-05-08 17:00:17.003 10853-10853/? D/NVRAM: NVRAM: NVM_GetLIDByName Lid =77
2025-05-08 17:00:17.003 10853-10853/? D/NVRAM: fail to open /sys/class/BOOT/BOOT/boot/boot_mode:
2025-05-08 17:00:17.003 10853-10853/? D/NVRAM: 77 is in new nvram partition!!!
2025-05-08 17:00:17.003 10853-10853/? D/NVRAM: New NVRAM partition name is /dev/block/by-name/proinfo.
2025-05-08 17:00:17.003 10853-10853/? D/NVRAM: RecNum is :1
2025-05-08 17:00:17.005 10853-10853/? D/NVRAM: 77 is in new nvram partition!!!
2025-05-08 17:00:17.006 10853-10853/? D/NVRAM: close File error!
2025-05-08 17:00:17.006 8807-8807/com.android.nvramapp D/NvRamUtils: flag = 0
写入时没有明显的log,就是报错close File error!。
product info 会被 EMMC 写保护挡下 power on write protect权限问题。由于有保护机制,所以取消。
修改的是write_protect_ab.c文件,而不是write_protect.c文件,是因为该项目开启了a/b分区。
vendor/mediatek/proprietary/bootable/bootloader/lk/platform/xxx/write_protect_ab.c
void write_protect_flow(void)
#endif
if (!bypass_wp) {
- ret = set_write_protect();
+ /*ret = set_write_protect();
if (ret != 0)
- pal_log_err("write protect fail! \n");
+ pal_log_err("write protect fail! \n");*/
pal_log_err("write protect Done! \n");
} else
pal_log_err("Bypass write protect! \n");
以下为简单的NvRamUtils工具类。
由于初始化有一定机率失败,所有多retry几次。
public class NvRamUtils {
private static final String TAG = "NvRamUtils";
private static final String PRODUCT_INFO_FILENAME = "/mnt/vendor/nvdata/APCFG/APRDEB" +
"/xxx";
/***** NvRamUtils - Place your offset below *****/
//@Description: Ensure there is no duplicated offset declared!
// NV offset - Please Try to use the index between 1024 - 2047
public static final int NV_LENGTH = 1024;
private static INvram agent;
private static final int MAX_RETRIES = 10;
private static final long RETRY_DELAY_MS = 100;
// 初始化INvram实例
public static boolean initializeNvramAgent() {
Log.d(TAG, "inner initializeNvramAgent");
int retries = 0;
while (retries < MAX_RETRIES) {
try {
Log.d(TAG, "inner initializeNvramAgent INvram getService");
// 尝试获取服务
agent = INvram.getService();
if (agent != null) {
Log.i(TAG, "NvramAgent initialized successfully");
return true; // 成功获取到 service,返回 true
}
// 如果 agent 为 null,表示获取失败
Log.e(TAG, "NvramAgent initialization failed, attempt " + (retries + 1) + " of " + MAX_RETRIES);
} catch (NoSuchElementException e) {
// 捕获 NoSuchElementException,如果 getService() 返回了 null 或其他问题
Log.e(TAG, "No such element exception occurred while getting NvramAgent service: " + e.getMessage());
} catch (RemoteException e) {
// 处理 RemoteException,通常是与硬件服务通信失败
Log.e(TAG, "RemoteException while getting NvramAgent service (attempt " + (retries + 1) + " of " + MAX_RETRIES + "): " + e.getMessage());
}
retries++;
// 如果重试次数小于最大次数,等待指定时间后重试
if (retries < MAX_RETRIES) {
try {
Log.i(TAG, "Retrying to initialize NvramAgent, attempt " + retries + " of " + MAX_RETRIES);
TimeUnit.MILLISECONDS.sleep(RETRY_DELAY_MS); // 等待一段时间后重试
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 恢复中断状态
Log.w(TAG, "Thread interrupted during retry sleep", e);
return false; // 如果线程中断,返回失败
}
}
}
Log.e(TAG, "Failed to initialize NvramAgent after " + MAX_RETRIES + " retries");
return false; // 最终失败
}
public static byte[] readNvRam(int index, int length) {
return read(PRODUCT_INFO_FILENAME, index, length);
}
public static byte[] read(String filePath, int index, int length) {
if (agent == null) {
Log.e(TAG, "NvRamAgent initialization failed");
return null;
}
try {
StringBuilder nvRamBuf = new StringBuilder();
if (agent == null) {
Log.e(TAG, "NvRamAgent is null");
return null;
}
String buff = agent.readFileByName(filePath, index + length);
Log.i(TAG, "Raw data:" + buff);
if (buff.length() < 2 * (index + length)) {
return null;
}
// Remove the \0 special character.
int macLen = buff.length() - 1;
for (int i = index * 2; i < macLen; i += 2) {
if ((i + 2) < macLen) {
nvRamBuf.append(buff.substring(i, i + 2));
} else {
nvRamBuf.append(buff.substring(i));
}
}
Log.d(TAG, "buff:" + nvRamBuf.toString());
String str = nvRamBuf.toString();
return HexDump.hexStringToByteArray(str.substring(0, str.length() - 1));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static boolean writeToNvRam(int index, byte[] buff) {
return write(PRODUCT_INFO_FILENAME, index, buff);
}
/**
* write a specified byte array into NvRAM, start with the specified index
*
* @param index the start position that need to be written
* @param buff the values that need to be written from the start position
* @return true when write succeeded, false when write failed
*/
public static boolean write(String filePath, int index, byte[] buff) {
// 检查 agent 是否已经初始化
if (agent == null) {
Log.e(TAG, "NvRamAgent is not initialized");
return false; // 如果 agent 为 null,说明未初始化,直接返回失败
}
try {
byte[] buffArr = readNvRam(0, NV_LENGTH);
for (int i = 0; i < buff.length; i++) {
buffArr[i + index] = buff[i];
}
ArrayList<Byte> dataArray = new ArrayList<>(NV_LENGTH);
for (int j = 0; j < NV_LENGTH; j++) {
dataArray.add(j, buffArr[j]);
}
int flag = agent.writeFileByNamevec(filePath, NV_LENGTH, dataArray);
Log.d(TAG, "flag = " + flag);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 将字节数组转换为字符串
*/
public static String byteArrayToString(byte[] byteArray) {
if (byteArray.length > 0) {
return String.valueOf(byteArray[0] & 0xFF); // 转为无符号的字符串
} else {
return "0"; // 如果字节数组为空,返回默认值 "0"
}
}
}
demo可以参考这个:NvRAM App层的使用
参考链接:
Android系统开发 android8之后版本读写Nvram
Android 9.0 MTK平台Nvram写sn号失败