USB UMS MTP设置过程

本文详细解析了Android系统中如何通过UsbSettings.java文件选择不同的USB模式(MTP、PTP、UMS),并深入探讨了相关Activity如UsbStorageActivity的触发机制以及通知弹出流程。

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

选择MTP,PTP,UMS的选项界面就定义在UsbSettings.java,选择其中一个选项时会执行以下代码。

packages/apps/Settings/src/com/android/settings/deviceinfo/UsbSettings.java

        if (preference == mMtp) {          
            mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MTP, true);
            updateToggles(UsbManager.USB_FUNCTION_MTP);
        } else if (preference == mPtp) {   
            mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_PTP, true);
            updateToggles(UsbManager.USB_FUNCTION_PTP);
        } else if(preference == mUms) {    
            mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MASS_STORAGE, true);
            updateToggles(UsbManager.USB_FUNCTION_MASS_STORAGE);
        }

updateToggle就是去让执行某些选项的选中与取消工作。

其中最重要的是mUsbManager.setCurrentFunction(),mUsbManger是这样得到的:

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
    }   

它的实现在frameworks/base/core/java/android/hardware/usb/UsbManager.java。

它的接口实现在frameworks/base/core/java/android/hardware/usb/IUsbManager.aidl

frameworks/base/services/java/com/android/server/usb/UsbService.java

/**    
 * UsbService manages all USB related state, including both host and device support.
 * Host related events and calls are delegated to UsbHostManager, and device related
 * support is delegated to UsbDeviceManager.
 */    
public class UsbService extends IUsbManager.Stub {
    private final Context mContext;
    private UsbDeviceManager mDeviceManager;
    private UsbHostManager mHostManager;
    private final UsbSettingsManager mSettingsManager;

这个界面就是"com.android.settings.UsbSettings" Activity。在frameworks/base/services/java/com/android/server/usb/UsbDeviceManager.java中被调用。

如果你选择了USB调试功能,还会弹出"com.android.settings.DevelopmentSettings" Activity,也是在UsbDeviceManager.java中被调用。关于UsbDevcieManager,我们以后再细看。

如果你选择了UMS,还会弹出"com.android.systemui.usb.UsbStorageActivity" Activity,就是“打开USB存储设备”的界面。它就义在定义在:
frameworks/base/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java。

这些界面只有在插入USB时才会有通知显示。在没有插USB的情况下,有些界面是没有入口的。我们就以UsbStorageActivity为例,介绍一下这些通知是怎么弹出来的。

通知是怎么弹出来的

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java

        // storage
        mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
        mStorageManager.registerListener(
                new com.android.systemui.usb.StorageNotification(context));
这里注册了监听函数com.android.systemui.usb.StorageNotification,这个只是针对Phone,对于平板,有tablet/TabletStatusBarPolicy.java

我们来看一下注册的com.android.systemui.usb.StorageNotification

frameworks/base/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java

public class StorageNotification extends StorageEventListener { 
    private static final String TAG = "StorageNotification";

    public StorageNotification(Context context) {
        mContext = context;

        mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
        final boolean connected = mStorageManager.isUsbMassStorageConnected();
        Slog.d(TAG, String.format( "Startup with UMS connection %s (media state %s)", mUmsAvailable,
                Environment.getExternalStorageState()));
        
        HandlerThread thr = new HandlerThread("SystemUI StorageNotification");
        thr.start();
        mAsyncEventHandler = new Handler(thr.getLooper());

        onUsbMassStorageConnectionChanged(connected);
    }

在构造函数里就调用了onUsbMassStorageConnectionChanged函数,它最终会调到updateUsbMassStorageNotification(),

    /** 
     * Update the state of the USB mass storage notification
     */
    void updateUsbMassStorageNotification(boolean available) {

        if (available) {
            Intent intent = new Intent();
            intent.setClass(mContext, com.android.systemui.usb.UsbStorageActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

            PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0); 
            setUsbStorageNotification(
                    com.android.internal.R.string.usb_storage_notification_title,
                    com.android.internal.R.string.usb_storage_notification_message,
                    com.android.internal.R.drawable.stat_sys_data_usb,
                    false, true, pi);
        } else {
            setUsbStorageNotification(0, 0, 0, false, false, null);
        }   
    }   

也就是说UsbStorageActivity和StorageNotification绑定在了一起,什么时候弹出这个通知,就可以进入这个Activity了。

如果连接了USB,就会在通知栏里显示USB选项的通知。如果没有连接,就会把这个通知给取消掉。那我们看一下,这个通知是怎么弹出来的。

StorageManager

frameworks/base/core/java/android/os/storage/StorageManager.java

    public void registerListener(StorageEventListener listener) {
        if (listener == null) {            
            return;
        }

        synchronized (mListeners) {        
            mListeners.add(new ListenerDelegate(listener));
        }
    }  
mListeners会被私有成员MountServiceBinderListener用到,而MountServiceBinderListener又是继承自IMountServiceListener.Stub,在构造函数里被注册。

    public StorageManager(Looper tgtLooper) throws RemoteException {
        mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
        if (mMountService == null) {
            Log.e(TAG, "Unable to connect to mount service! - is it running yet?");
            return;
        }
        mTgtLooper = tgtLooper;
        mBinderListener = new MountServiceBinderListener();
        mMountService.registerListener(mBinderListener);
    }
所以关键还是在mMountService。
### UMS、RNDIS 和 MTP 模式的切换方法 #### 1. **UMS (USB Mass Storage)** 切换配置 UMS 是一种传统的 USB 存储模式,允许设备作为外部硬盘被主机识别。然而,在 Android 5.1 及以上版本中已不再支持该模式[^4]。 - 如果需要启用 UMS 模式,则需依赖于旧版 Android 设备或自定义 ROM 的支持。 - 对于开发人员而言,可以通过修改 `fstab` 文件以及调整 `/system/etc/vold.conf` 来重新激活此功能。具体操作如下: ```bash # 修改 vold.conf 中的 ums 启动参数 vold.fstab=/etc/vold.fstab ``` 需要注意的是,现代 Android 系统更倾向于使用 MTP 或者其他高级协议代替传统 UMS 模式。 --- #### 2. **RNDIS (Remote Network Driver Interface Specification)** 切换配置 RNDIS 主要用于将移动设备模拟成网卡,从而实现网络共享等功能。它通常应用于调试环境下的 ADB 连接或者热点分享场景。 - 在 Android 上开启 RNDIS 功能的方法之一是通过开发者选项完成: - 打开「设置」-> 「关于手机」 -> 多次点击「版本号」直到解锁开发者模式; - 返回至「设置」-> 「系统」-> 「开发者选项」; - 将「网络连接类型」设为「RNDIS(以太网)」即可[^3]。 对于某些定制化固件来说,也可以直接编辑内核启动脚本: ```bash # 设置 kernel 参数以强制加载 rndis 驱动模块 androidboot.mode=rndis ``` 上述命令可通过 fastboot 工具传递给目标设备。 --- #### 3. **MTP (Media Transfer Protocol)** 切换配置 MTP 协议专为多媒体文件传输设计,广泛适用于当前主流智能手机和平板电脑产品线之中。相比起简单的磁盘映射机制,它可以更好地保护内部存储结构免受意外破坏。 - 默认情况下,当用户选择「仅充电」「文件传输」等 USB 使用目的时,实际上就是启用了 MTP 方式[^2]。 - 若要手动指定进入 MTP 模态,可尝试以下步骤: - 插入 USB 数据线后弹出提示框里选取对应项; - 若无自动询问窗口显示,则前往「通知栏」寻找相关联菜单条目进行更改。 另外值得注意的一点在于部分厂商可能会额外提供专属应用商店下载链接来辅助完成此类设定过程。 --- ### 总结说明 综上所述,针对不同需求可以选择适合自己的通信手段并加以实施部署。尽管如此还是建议优先选用官方推荐途径以免造成不必要的麻烦。 ```python def switch_mode(mode="mtp"): """Switch between different modes based on user preference.""" if mode.lower() == "ums": print("Enabling UMS Mode...") # Code to enable UMS goes here. elif mode.lower() == "rndis": print("Enabling RNDIS Mode...") # Code to enable RNDIS goes here. else: print(f"Defaulting to {mode.upper()} Mode.") # Default code block for enabling MTP. switch_mode() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值