Android/C/C++ 中解决 USB UnMount(禁止USB端口)

article/2025/10/12 11:10:04

引:因为某些特殊需求,需要在某些设备接入车机的时候,动态UnMount USB设备,因为代码其中有一些方法是自定义过的,所以该文章仅供思路参考。

(20200319 更新):在后续跟进中,发现如果卸载U盘的话,(U盘资源未被释放,可以类似正在播放U盘里的音乐和视频或者在扫描U盘,如果需要Unmount U盘的时候)vold检测到了extractor进程正在提取id3,规定时间内没有释放优盘资源,所以vold把它kill了,会执行ProcessKiller ,最后会走到system/vold/Utils.cpp下的KillProcessesUsingPath()下,在KillProcessesUsingPath_1 和KillProcessesUsingPath_2 之间会Sleep 5秒,所以就会导致,广播:android.intent.action.MEDIA_EJECT 和 android.intent.action.MEDIA_UNMOUNTED 相差有6s + ,这里是不可避免的。

status_t KillProcessesUsingPath(const std::string& path) {LOG(WARNING) << "KillProcessesUsingPath" ;const char* cpath = path.c_str();if (Process::killProcessesWithOpenFiles(cpath, SIGINT) == 0) {return OK;}LOG(WARNING) << "KillProcessesUsingPath_1" ;if (!VolumeManager::shutting_down) sleep(5);LOG(WARNING) << "KillProcessesUsingPath_2" ;if (Process::killProcessesWithOpenFiles(cpath, SIGTERM) == 0) {return OK;}
...............

一:第一种方法是在java层做处理
如下需要涉及到/System/Vold 和frameWork 以及device层的修改。
其实主要是在framework层的修改,用到的方法也很简单,需要用到:

StorageManager
StorageVolume

根据我当前项目的需求,是要求插入某一个device 的时候,判断出是当前需要的设备的时候,卸载/禁止USB2 端口。

里面可能有一些方法是已经重写过的,正规的API 不一定有,比如getUsbId()就没有,不过还是如篇头所说提供下解决思路吧。

思路:为了设备使用期间,USB2不能被使用,除了主动unmount之后,还需要保证下一次USB插拔的时候拦截USB挂载消息。(主动卸载只是生效一次),所以步骤就是2个,先主动unmount,在设置prop属性在Vold中拦截USB挂载消息。

vold简介:
 vold进程接收来自内核的外部设备消息,用于管理和控制Android平台外部存储设备,包括SD插拨、挂载、卸载、格式化等;当外部设备发生变化时,内核通过Netlink发送uEvent格式的消息给用户空间程序,Netlink
是一种基于异步通信机制,在内核与用户应用间进行双向数据传输的特殊 socket,用户态应用使用标准的socket API 就可以使用netlink 提供的强大功能。

涉及的主要文件:
Framework层主要看MountService.java和NativeDaemonConnector.java;
Native层主要看NetlinkManager.cpp, NetlinkHandler.cpp,
VolumeManager.cpp,CommandListener.cpp

核心代码:

*** <P>if device Connected Unmount USB2</P>* <P>beibei 20191231</P>*/
private StorageManager mStorageManager;
private final String UNMOUNT_DEVICE_ID = "USB2";
private void StartUnmountUsbAccessory()  {Log.d(TAG, "StartUnmountUsbAccessory");try {if (mStorageManager == null){Log.d(TAG, "mStorageManager is null");mStorageManager = mContext.getSystemService(StorageManager.class);}List<StorageVolume> volumes =mStorageManager.getStorageVolumes();for (int i = 0; i < volumes.size(); i++) {Log.d(TAG, "StorageVolume start foreach");//if usb the not's emulated/Primary , It's not an external usbif (!volumes.get(i).isEmulated() && !volumes.get(i).isPrimary()) {Log.d(TAG, "isEmulated && isPrimary");if (UNMOUNT_DEVICE_ID.equals(volumes.get(i).getUsbId())) {Log.d(TAG, "imStorageManager.unmount Success");mStorageManager.unmount(volumes.get(i).getId());}}}} catch(Exception e){e.printStackTrace();}}

解释:通过StorageManager 获取到StorageVolume,并通过循环遍历,之后通过isPrimary(不是外部存储卷)和isEmulated (不是模拟卷)过滤后,
下面的就是匹配自己想要UnMount的ID了,匹配成功后,调用mStorageManager.unmount
**注意:**该方法调用会抛出System.error ,需要处理异常。
必须增加 try catch

/*** Returns true if the volume is the primary shared/external storage, which is the volume* backed by {@link Environment#getExternalStorageDirectory()}.*/
public boolean isPrimary() {return mPrimary;
}/*** Returns true if the volume is emulated.** @return is removable*/
public boolean isEmulated() {return mEmulated;
}

然后其次就是 设置 prop

case MSG_PROJECTION_DEVICE_CONNECTED_SUCCESS:StartUnmountUsbAccessory();SystemProperties.set(UNMOUNT_DEVICE_PROP_STATE,"true");break;
case MSG_PROJECTION_DEVICE_DISCONNECTED_SUCCESS:SystemProperties.set(UNMOUNT_DEVICE_PROP_STATE,"false");break;

关键的拦截USB mount的在/system/vold/ NetlinkHandler.cpp,的onEvent消息事件中。

void NetlinkHandler::onEvent(NetlinkEvent *evt) {VolumeManager *vm = VolumeManager::Instance();const char *subsys = evt->getSubsystem();if (!subsys) {SLOGW("No subsystem found in netlink event");return;}/***Add usb2 disable temporary scheme 20191231 start***/char args[PROPERTY_VALUE_MAX];property_get("vendor.device.usb2",args,"false");if (strcmp(args,"true")==0){const char *path = evt->findParam("DEVPATH");if (strstr(path,USB_2_PATH)!=NULL){SLOGW("DISABLE USB2");return;}}/***Add usb2 disable temporary scheme 20191231  end***/if (!strcmp(subsys, "block")) {vm->handleBlockEvent(evt);}
}

至于Prop怎么设置,百度下,一般写在device/fsl/… 的 .mk文件中
https://blog.csdn.net/qq_31332467/article/details/104751769
Ps: PRODUCT_PROPERTY_OVERRIDES +=
vendor.device.usb2 = false

二:第二种可以在C++ 层
主要的一个代码就是 echo shell 命令

 #include<stdlib.h>system("echo ‘1-1.2" >/sys/bus/usb/drivers/usb/unbind");

思路步骤是这样的:
在C++代码中找到合适的位置,先判断出什么情况下,接入什么设备需要unMound USB,增加tag,当满足的时候就执行system(“echo ‘1-1.2” >/sys/bus/usb/drivers/usb/unbind");
这个我也是在串口命令进行过测试,实际在代码中,我没有测试过,因为有了第一种方法。

测试方法有效性:
串口进入到Android板子内部:
解绑:echo “1-1.2” > unbind
绑定:echo “1-1.2” > bind
具体代码中实际应用没有测试。

在这里插入图片描述


http://chatgpt.dhexx.cn/article/xQ6ubdy5.shtml

相关文章

linux移动硬盘unmount报错处理

备份数据用的移动硬盘unmount时报&#xff1a; 通过fuser命令来kill掉设备进程&#xff0c;再unmount移动设备 先看fuser命令帮助信息&#xff1a; [rootathenadb2 ~]# fuser -helpUsage: fuser [ -a | -s | -c ] [ -n SPACE ] [ -SIGNAL ] [ -kimuv ] NAME... [ - ] [ -n SPAC…

虚拟机 报错:Unmount and run xfs_repair

1&#xff0c;启动虚拟机的时候&#xff0c;摁 E 键 找到linux16 这一行(在fi下一行) 的最后&#xff0c;添加&#xff1a; rd.break 摁 &#xff1a;ctrlx进入救援模式 2&#xff0c;执行&#xff1a;umount /dev/sda3 xfs_repair -L /dev/sda3 …

VMware 安装Centos7 虚拟机 报Unmount and run xfs_repair

VMware 安装Centos7 虚拟机 报Unmount and run xfs_repair 问题描述 安装完虚拟机后重启无法进入用户登录界面 报错&#xff1a;Unmount and run xfs_repair 原因&#xff1a; dm-0分区损坏 解决办法 卸载目录 umount /dev/mapper/centos-root 修复目录 xfs_repair -L…

linux 开机遇见unmount and run xfs_repair

vmware 开机提示 看不懂反正提示 dm-0 没有正确挂载&#xff0c;需要修复 直接上干货执行如下两条命令 ls -l /dev/mapper xfs_repair /dev/mapper/cl_root 或是 xfs_repair -L /dev/mapper/cl_root echo $? 如果返回零&#xff0c;代表成功 最后重启服务器即可 init 6

Linux虚拟机(lvm)报Unmount and run xfs_repair

原因&#xff1a;因为突然断电&#xff0c;导致机器关闭 结果&#xff1a;发现有一台虚拟机无法启动&#xff0c;一直报错 Unmount and run xfs_repair 分析&#xff1a;主机异常掉电后里面的虚拟机无法启动&#xff0c;主要是损坏的分区 解决办法&#xff1a; 原因&#x…

Ubuntu远程装载硬盘Mount and unmount disk

小虎本来以为Ubuntu&#xff08;Linux系统&#xff09;不能够远程装载硬盘&#xff0c;每次重开机都要线下重新装载硬盘。但是苦于工作站不在身边&#xff0c;跑来跑去太麻烦&#xff0c;所以想远程装载一下。 解决方法 遍历搜索所有硬盘。找到对应名字。 lsblk创建一个文件…

mount unmount oracle,umount- 0506-349 Cannot unmount -dev-cd0- The requested reso

umount- 0506-349 Cannot unmount -dev-cd0- The requested reso (2011-12-21 04:20:37) 标签&#xff1a; requested 杂谈 umount: 0506-349 Cannot unmount /dev/cd0: The requested reso请问&#xff1a;我在安装oracle的时候&#xff0c;当系统提示我放入第二张光盘的时候&…

umount卸载磁盘_如何使用umount命令在Linux,Ubuntu,CentOS中卸载磁盘

umount卸载磁盘 Linux distributions like Ubuntu, Debian, CentOS, RHEL, and others use disks by mounting them to the file system. We have already examined mount command in the following tutorial. In this tutorial we will learn how to umount the disk in a Lin…

Linux之磁盘管理df、du、mount 、unmount 命令

1、Linux磁盘管理常用命令为 df、du df &#xff1a;列出文件系统的整体磁盘使用量du&#xff1a;检查磁盘空间使用量 2、df 列出文件系统的整体磁盘使用量 df命令参数功能&#xff1a;检查文件系统的磁盘空间占用情况。可以利用该命令来获取硬盘被占用了多少空间&#xff0c;目…

strtok 函数

C 库函数 - strtok() C 标准库 - <string.h> 描述 C 库函数 char *strtok(char *str, const char *delim) 分解字符串 str 为一组字符串&#xff0c;delim 为分隔符。 声明 下面是 strtok() 函数的声明。 char *strtok(char *str, const char *delim) 参数 str -…

C语言strstr函数与strtok函数详解

C语言strstr函数与strtok函数详解 前言一、strstr函数1.函数原型2.函数参数、返回值解析3.strstr 函数模拟实现 二、strtok函数1.函数原型2.函数参数、返回值解析3.注意事项3.strtok 函数实现 前言 strstr() 函数与 strtok() 函数都属于字符串查找函数。 一、strstr函数 1.函…

strtok函数的实现(分步详细解释配图)

目录 函数大概的运行实现 1.定义一些变量 2.开始的一些条件 3.去掉pc前面一些需要被剪掉的字符 4.返回值ret的初始化 5.找到下一个分隔符 5.补\0 6.结束返回 完整代码 头文件&#xff1a;#include <string.h> 定义函数&#xff1a;char * strtok(char *s, co…

strtok函数及其模拟

1.strtok函数的参数和返回值 参数&#xff1a;第一个参数指定一个字符串&#xff0c;它包含了0个或者多个由del字符串中一个或者多个分隔符分割的标 记。 第二个参数del参数是个字符串&#xff0c;定义了用作分隔符的字符集合。 返回值&#xff1a; 如果找到分割符号&#xff…

详解 strtok 函数以及模拟实现

目录 一、strtok 函数的介绍 二、strtok 函数的模拟实现 一、strtok 函数的介绍 函数原型&#xff1a; char* strtok(char* str, const char* delimiters); delimiter n.[计]分隔符&#xff0c;定界符&#xff08;a character that marks the beginning or end of a unit o…

strtok(), strtok_s() 字符串分割函数

strtok(), strtok_s() 字符串分割函数 //strtok()函数原型/*_Check_return_ _CRT_INSECURE_DEPRECATE(strtok_s) _CRTIMP char * __cdecl strtok(_Inout_opt_z_ char * _Str, _In_z_ const char * _Delim);*/ 当strtok()在参数_Str的字符串中发现参数_Delim中包涵的分割字符时…

strtok函数与函数用法实例

一&#xff1a;函数简介&#xff1a; 使用strtok函数需要索引头文件#include<string.h>,strtok函数通常用于分割以及重组。被特殊字符间隔的字符串。 strtok的函数原型为char *strtok(char *str, char *sep&#xff09;strtok()在参数str的字符串中发现参数sep中包含的…

c语言中strtok函数详解,手把手教你自主实现字符串切割函数,内附详细代码。

函数功能简介&#xff1a; 对字符串str进行切割&#xff0c;切割的标志为字符指针q指向的这两个字符 “# *”&#xff1b;。 但是在对这个函数进行调用时&#xff0c;只有在第一次调用时&#xff0c;才会将str这个字符串的首地址传递过去&#xff0c;后面再进行调用时&#xf…

strtok函数详解 看这一篇就够了-C语言(函数讲解、函数实现、使用用法举例、作用)

strtok()函数用于&#xff1a; 将字符串拆分为标记 函数介绍 函数声明&#xff1a;char * strtok ( char * str, const char * delimiters ); 头 文 件&#xff1a;#include <string.h> 返 回 值&#xff1a; 返回值为char * 类型 。如果找到标记&#xff0c;则为指向…

C/C++字符串函数strtok()详解

函数作用 找到与delimiter相同的地方&#xff0c;将其截断&#xff0c;并返回str 函数理解 第一个参数str是待切割字符串 第二个参数delimiter是分隔符字符串 返回值为char * &#xff0c;一般默认返回str的地址 strtok() 的原理是将查找到与delimiter相同的部分字符串的…

strtok()函数的使用以及注意事项

一、函数的简介 函数原型&#xff1a;char *strtok(char *s, char *delim) 功能&#xff1a;作用于字符串s&#xff0c;以delim中的字符为分界符&#xff0c;将s切分成一个个子串&#xff1b;如果&#xff0c;s为空值NULL&#xff0c;则函数保存的指针SAVE_PTR在下一次调用中将…