qcom platform 子系统(7)

本文介绍了一个名为subsystem_ramdump的工具,该工具用于在Android设备上收集内存转储(RAM Dump)。文章详细解释了如何通过命令行参数指定转储位置、启用日志记录等功能,并介绍了工具的主要工作流程,包括初始化、轮询RAM Dump文件和生成转储文件的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/******************************************************************************/
/*---用户空间:subsystem_ramdump
service ss_ramdump /system/bin/subsystem_ramdump 2
    class late_start
    group system
---*/
/******************************************************************************/
static void ssr_tool_helper(void)
{
ALOGI("Usage:./system/bin/subsystem_ramdump [arg1] [arg2] [arg3]");
ALOGI("[arg1]: (1/2) Ramdump location: 1: eMMC: /data/ramdump or 2: SD card: /sdcard/ramdump");
ALOGI("[arg2]: (1/0) 1: Enable RPM log / 0: Disable RPM log");
ALOGI("[arg3]: (1/0) 1: Enable qdss ramdump / 0: Disable qdss ramdump");
}


static int parse_args(int argc, char **argv)
{
int location, rpmlog, qdss;


ssr_tool_helper();
if (argc == 1) {
// Use default ramdump location; disable rpm log ; disable qdss ramdump;
ALOGI(" Using default ramdump location 1: eMMC: /data/ramdump");
ALOGI(" Using default 0: Disable RPM log");
ALOGI(" Using default 0: Disable qdss ramdump");


location = 1;
rpmlog = 0;
qdss = 0;
}
}


#define DUMP_SETTING "/sys/module/subsystem_restart/parameters/enable_ramdumps"
static int ssr_check_ramdump_setting(void)
{
int ret = 0;
int fd;
char buf[2];


if ((fd = open(DUMP_SETTING, O_RDONLY)) < 0) {
}


if (read(fd, buf, 2) <= 0) {
}


if (buf[0] == '1') {
ret = 0;
} else if (buf[0] == '0') {
ret = -EINVAL;
} else {
ALOGE("Invalid ramdump setting %s", buf);
ret = -EINVAL;
}
return ret:
}


/*遍历/dev: 找到ramdump_xxx的设备:保存到全局变量:ramdump_list[] and pfd_num*/
static int ssr_search_pil_ramdump(void)
{
int ret = 0;
int i = 0;
struct dirent *dir_p;
DIR *dir_s;


dir_s = opendir(PIL_RAMDUMP_DIR);
while ((dir_p = readdir(dir_s)) != NULL) {
if (strncmp(dir_p->d_name, DUMP_HEAD_STR, 8) == 0) {
strlcpy(ramdump_list[i], dir_p->d_name, PIL_NAME_SIZE);
i++;
}
}
/* Store pil ramdump number */
pfd_num = i;
closedir(dir_s);


return ret;
}


static int ssr_ramdump_init(ramdump_s *dump, int androidBuild )
{
int ret = 0;
int i;


/* check if ramdump folder can be created */
if (check_folder(dump->dir) != 0) {
ALOGI("Attemping to create %s", dump->dir);
if ((ret = create_folder(ramdump.dir)) < 0) {
ALOGE("Unable to create %s", dump->dir);
goto open_error;
}
}


if ( androidBuild ) {
/* init ramdump semaphore */
if (sem_init(&ramdump_sem, 0, 0) != 0) {
ret = -EINVAL;
goto ramdump_semaphore_error;
}


/* init qdss semaphore */
if (sem_init(&qdss_sem, 0, 0) != 0) {
ret = -EINVAL;
goto qdss_semaphore_error;
}
}


/* init ramdump parameters */
for (i = 0; i < DUMP_NUM; i++) {
dump->fd[i] = -1;
dump->dev[i] = -1;
}


/* open fd in ramdump list */
if ((ret = open_ramdump_fd(dump)) < 0) {
ALOGE("Failed to open ramdump devices");
goto open_ramdump_error;
}


/* Store fd to polling struct */
for (i = 0; i < pfd_num; i++) {
pfd[i].fd = dump->fd[i];
pfd[i].events = POLLIN;
pfd[i].revents = 0;
}
ssr_flag = 0;


return ret;
}
poll:
RETURN VALUE
On success, a positive number is returned; this is the number of structures which have nonzero revents fields 
(in other words, those descriptors with events or errors reported).  
A value of 0 indicates that the call timed out and no file descriptors were ready.  
On error, -1 is returned, and errno is set appropriately.


int main(int argc, char *argv[])
{
int ret = 0;
int i;
char timestamp[TIMEBUF_SIZE];
int timeout = -1;
char *ssname = NULL;
/* Loop forever and poll */
while (1) {
/* Poll all ramdump files */
ret = poll(pfd, pfd_num, timeout);
if (ret<0) {
ALOGE("Polling ramdump failed: %d", ret);
break;
} else if (0==ret) {


}


if (-1==timeout) {
ssname = NULL;
timeout = 300;
}


/* Get current time */
if (get_current_timestamp(timestamp, TIMEBUF_SIZE) == NULL) {
}
/* Collect ramdumps */
for (i = 0; i < pfd_num; i++) {
ret = generate_ramdump(i, &ramdump, timestamp);
/* If ramdump generation is failed, exit the program */
if ((ret > 0) && (NULL == ssname) && (strncmp(ramdump_list[ramdump.dev[i]], DUMP_SMEM_STR, 12))) {
ssname = ramdump_list[ramdump.dev[i]];
}
}
}
}


int generate_ramdump(int index, ramdump_s *dump, char *tm)
{
int ret = 0;
int numBytes = 0;
int totalBytes = 0;
int fd = -1;
char *rd_buf;
char f_name[FILENAME_SIZE];
int should_skip = 0;


/* Check to see if we have anything to do */
if ((pfd[index].revents & POLLIN) == 0)
goto skip_dump_generation;


/* Read first section of ramdump to determine type */
while ((numBytes = read(pfd[index].fd, rd_buf, CHK_ELF_LEN)) > 0) {
*(rd_buf + numBytes) = '\0';
if (should_skip)
strcpy(f_name, "/dev/null");
else if (strstr(rd_buf, STR_ELF))
ssr_ramdump_filename(index, dump, f_name, tm, 1);
else
ssr_ramdump_filename(index, dump, f_name, tm, 0);


/* Open the output file */
fd = open(f_name, O_WRONLY | O_CREAT, S_IRUSR);


/* Write first section ramdump into file and exit loop */
ret = write(fd, rd_buf, numBytes);
totalBytes += numBytes;
break; /*这里有个break*/
}


/* Read data from the ramdump, and write it into the output file */
while ((numBytes = read(pfd[index].fd, rd_buf, BUFFER_SIZE)) > 0) {
ret = write(fd, rd_buf, numBytes);
if (ret < 0) {
ALOGE("Failed to write to dump file %s",
f_name);
goto dump_write_error;
}
totalBytes += numBytes;
}


/* Make sure things are written */
fsync(fd);
}


/*************产生ramdump 文件后的处理*******************/


ALOGE("Ramdump: Polling ramdump timeout: %d\n", ret);
ALOGE("compress and clear the crash file[%s]\n", dump_name_buf);
snprintf(cmd_buf, CMD_SIZE, "busybox tar czf %s/%s%s.tgz %s", ramdump.dir, ssname, timestamp, dump_name_buf);
cmd_result = system(cmd_buf);
ALOGE("tar ramdump, cmd_result:0x%x",cmd_result);


sprintf(cmd_buf, "logcat -t 3000 -f %s/%s%s_logcat.log" ,ramdump.dir,ssname,timestamp);
(void)system(cmd_buf);


sprintf(cmd_buf, "dmesg > %s/%s%s_dmesg.log", ramdump.dir,ssname,timestamp);
(void)system(cmd_buf);


sprintf(cmd_buf, "getprop > %s/%s%s_props.txt", ramdump.dir,ssname,timestamp);
(void)system(cmd_buf);


/* 这堆想干什么?
char tmpdump[32] = "/sdcard/sysmatlog/tmpmdmdump";
char srcdump[64] = "";
snprintf(srcdump,sizeof(srcdump), "%s%s", ssname, timestamp);
char dstdump[64] = "";
snprintf(dstdump,sizeof(dstdump),"%s.",srcdump);
int mat_fd = -1;
sprintf(cmd_buf, "rm -r %s + mkdir %s", tmpdump, tmpdump);
char matshcmd[1024] = "";
sprintf(matshcmd, "[execmds=%s+busybox cp %s/%s* %s/+busybox split -b 3m -a 1 %s/%s.tgz %s/%stgz. + rm %s/%s.tgz+logorgfilespath=%s]@subsysRD_%s ", cmd_buf, ramdump.dir, srcdump, tmpdump, tmpdump, srcdump, tmpdump, dstdump, tmpdump, srcdump, tmpdump, ssname);
ALOGE("matshcmd: %s", matshcmd);
mat_fd = open("/dev/sysmatdrv", O_WRONLY);
*/
<think>嗯,用户遇到了一个Android构建错误,具体是在Android.bp文件中,模块'android.hardware.biometrics.face@1.0-service.face'依赖的两个模块'android.hardware.biometrics.face-V1-ndk_platform'和'android.hardware.biometrics.common-V1-ndk_platform'未定义。我需要帮他解决这个问题。 首先,根据引用[2],HIDL的软件包结构是按特定路径存放的。用户提到的模块可能属于android.hardware.*,所以应该位于hardware/interfaces/下。检查对应的路径是否存在这些模块的源代码,比如biometrics/face和common目录下是否有正确的版本目录,比如1.0。 然后,如果路径正确,但模块未定义,可能这些模块没有被正确声明。需要确认对应的Android.bp或Android.mk文件是否存在,并且模块名称是否正确。比如,检查是否有cc_library_shared或类似的定义,模块名是否包含正确的版本后缀。 另外,依赖关系是否正确?可能用户在自己的模块中引用了错误的模块名,或者版本号不匹配。比如,是否应该使用V1.0而不是V1,或者是否需要添加ndk_platform的后缀?根据引用[2],HIDL的软件包结构可能会有特定的命名规则,需要确保模块名称与依赖声明一致。 还有,可能需要添加相应的库到依赖中。比如,在Android.bp中使用shared_libs或static_libs包含这些模块。或者,如果这些模块是NDK的,可能需要使用stubs或vendor_available属性。引用[1]提到的HIDL接口可能需要特定的依赖配置。 另外,查看错误信息是否有其他提示,比如路径是否正确。比如引用[3]中的错误是因为路径不存在,所以用户需要检查模块的路径是否实际存在,或者是否有拼写错误。比如,face-V1-ndk_platform的路径是否正确,是否存在对应的源代码文件。 可能还需要检查整个项目的构建配置,是否有子模块未包含,或者是否需要更新仓库到正确版本。有时候,模块缺失是因为代码库没有完全同步,或者分支不正确。 总结可能的解决步骤:1.确认依赖模块的路径和源代码存在;2.检查依赖模块的Android.bp定义是否正确;3.修正当前模块的依赖声明;4.确保整个项目构建配置正确,同步最新代码。如果这些步骤都检查过了,可能需要进一步查看构建日志或文档。</think>### 问题分析 构建错误表明模块 `android.hardware.biometrics.face@1.0-service.face` 依赖的两个 NDK 平台库未定义。这类问题通常与 **模块路径、依赖声明或构建规则** 有关[^3]。 --- ### 逐步解决方案 #### 1. **确认依赖模块的源代码路径** 根据 HIDL 的软件包规则[^2]: - `android.hardware.biometrics.face` 应位于 `hardware/interfaces/biometrics/face/1.0/` - `android.hardware.biometrics.common` 应位于 `hardware/interfaces/biometrics/common/1.0/` **检查**: - 确认路径下存在 `Android.bp` 文件,并包含对 NDK 平台库的定义(例如 `cc_library_shared` 或 `cc_library_static`)。 - 若路径缺失或文件未生成,需同步代码库或手动添加。 --- #### 2. **验证模块命名格式** NDK 平台库的命名需符合以下格式: - `android.hardware.biometrics.face-V1-ndk_platform` - `android.hardware.biometrics.common-V1-ndk_platform` **修改依赖声明**: 在 `Android.bp` 中,确保依赖项与模块名称完全匹配: ```python shared_libs: [ "android.hardware.biometrics.face-V1-ndk_platform", "android.hardware.biometrics.common-V1-ndk_platform", ], ``` --- #### 3. **检查 NDK 库的构建规则** 若依赖的模块是 NDK 接口库,需确保其已通过 `cc_library` 定义,并包含 `vendor_available: true` 或 `stubs` 配置。例如: ```python cc_library_shared { name: "android.hardware.biometrics.face-V1-ndk_platform", srcs: ["IFace.cpp"], vendor_available: true, shared_libs: [ "libbase", "libhidlbase", ], } ``` --- #### 4. **同步代码并清理构建缓存** - 执行 `repo sync` 确保代码最新。 - 清理构建缓存: ```bash make clean rm -rf out/ ``` --- ### 根本原因总结 1. **依赖模块未定义**:路径缺失或命名错误导致构建系统无法找到库。 2. **构建规则不匹配**:NDK 平台库未正确声明为 `shared_libs` 或缺少关键属性。 3. **代码未同步**:依赖模块可能存在于远程仓库但未拉取到本地。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值