Android 6.0 MTP

本文详细解析了MTP(Media Transfer Protocol)的工作流程和技术细节。从USB状态广播开始,介绍了如何通过MtpReceiver监听并响应USB状态变化,进一步启动MtpService进行MTP模式的开启与关闭操作。

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

相关代码

  1. packages/providers/MediaProvider/src/com/android/providers/media/MtpReceiver.java    
  2. packages/providers/MediaProvider/src/com/android/providers/media/MtpService.java    
  3. packages/providers/MediaProvider/src/com/android/providers/media/MediaProvider.java    
  4. frameworks/base/media/java/android/mtp/MtpServer.java    
  5. frameworks/base/media/java/android/mtp/MtpDatabase.java    
  6. frameworks/base/media/java/android/mtp/MtpStorage.java    
  7. frameworks/base/media/jni/android_mtp_MtpServer.cpp    
  8. frameworks/base/media/jni/android_mtp_MtpDatabase.cpp    
  9. frameworks/av/media/mtp/MtpServer.h    
  10. frameworks/av/media/mtp/MtpServer.cpp
  11. frameworks/av/media/mtp/MtpDatabase.h

MTP主要处理逻辑


一、UsbDevicemanager发送usb状态广播

UsbDevicemanager发送ACTION_USB_STATE的广播,来通知usb状态的变化

private void updateUsbStateBroadcast() {  
    // send a sticky broadcast containing current USB state  
    boolean UsbDataUnlocked = isUsbTransferAllowed() && mUsbDataUnlocked ;  
    Intent intent = new Intent(UsbManager.ACTION_USB_STATE);  
    intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING  
            | Intent.FLAG_RECEIVER_FOREGROUND);  
    intent.putExtra(UsbManager.USB_CONNECTED, mConnected);  
    intent.putExtra(UsbManager.USB_CONFIGURED, mConfigured);  
    intent.putExtra(UsbManager.USB_DATA_UNLOCKED, UsbDataUnlocked);  
  
    if (mCurrentFunctions != null) {  
        String[] functions = mCurrentFunctions.split(",");  
        for (int i = 0; i < functions.length; i++) {  
            intent.putExtra(functions[i], true);//这里是各个functions的状态  
        }  
    }  
  
    if (DEBUG) Slog.d(TAG, "broadcasting " + intent + " , connected: " + mConnected  
                            + " , configured: " + mConfigured + " , UsbDataUnlocked: " + UsbDataUnlocked  
                            + " , CurrentFunctions: " + mCurrentFunctions);  
    mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);  


MtpReceiver.java

这个属于应用的代码,先监听开机广播,然后注册ACTION_USB_STATE广播,最后在handleUsbState的时候会启动MtpService

   private void handleUsbState(Context context, Intent intent) {
        Bundle extras = intent.getExtras();
        boolean connected = extras.getBoolean(UsbManager.USB_CONFIGURED);
        boolean mtpEnabled = extras.getBoolean(UsbManager.USB_FUNCTION_MTP);
        boolean ptpEnabled = extras.getBoolean(UsbManager.USB_FUNCTION_PTP);
        boolean unlocked = extras.getBoolean(UsbManager.USB_DATA_UNLOCKED);
        // Start MTP service if USB is connected and either the MTP or PTP function is enabled
        if (connected && (mtpEnabled || ptpEnabled)) {
            intent = new Intent(context, MtpService.class);
            intent.putExtra(UsbManager.USB_DATA_UNLOCKED, unlocked);
            if (ptpEnabled) {
                intent.putExtra(UsbManager.USB_FUNCTION_PTP, true);
            }
            if (DEBUG) { Log.d(TAG, "handleUsbState startService"); }
            context.startService(intent);
            // tell MediaProvider MTP is connected so it can bind to the service
            context.getContentResolver().insert(Uri.parse(
                    "content://media/none/mtp_connected"), null);
        } else {
            boolean status = context.stopService(new Intent(context, MtpService.class));
            if (DEBUG) { Log.d(TAG, "handleUsbState stopService status=" + status); }
            // tell MediaProvider MTP is disconnected so it can unbind from the service
            context.getContentResolver().delete(Uri.parse(
                    "content://media/none/mtp_connected"), null, null);
        }
    }


MtpService.java

public int onStartCommand(Intent intent, int flags, int startId) {
        mUnlocked = intent.getBooleanExtra(UsbManager.USB_DATA_UNLOCKED, false);//该值为true默认MTP显示文件,否则就算默认MTP也是不显示磁盘内容的
        if (LOGD) { Log.d(TAG, "onStartCommand intent=" + intent + " mUnlocked=" + mUnlocked); }
        synchronized (mBinder) {
            updateDisabledStateLocked();
            mPtpMode = (intent == null ? false
                    : intent.getBooleanExtra(UsbManager.USB_FUNCTION_PTP, false));
            String[] subdirs = null;
            if (mPtpMode) {
                int count = PTP_DIRECTORIES.length;
                subdirs = new String[count];
                for (int i = 0; i < count; i++) {
                    File file =
                            Environment.getExternalStoragePublicDirectory(PTP_DIRECTORIES[i]);
                    // make sure this directory exists
                    file.mkdirs();
                    subdirs[i] = file.getPath();
                }
            }
            final StorageVolume primary = StorageManager.getPrimaryVolume(mVolumes);
            if (mDatabase != null) {
                mDatabase.setServer(null);
            }
            mDatabase = new MtpDatabase(this, MediaProvider.EXTERNAL_VOLUME,
                    primary.getPath(), subdirs);
            manageServiceLocked();
        }

        return START_REDELIVER_INTENT;
    }


private void manageServiceLocked() {
        final boolean isCurrentUser = UserHandle.myUserId() == ActivityManager.getCurrentUser();
        if (mServer == null && isCurrentUser) {
            Log.d(TAG, "starting MTP server in " + (mPtpMode ? "PTP mode" : "MTP mode"));
            Log.d(TAG,"mMtpDisabled " + mMtpDisabled);
            mServer = new MtpServer(mDatabase, mPtpMode);
            mDatabase.setServer(mServer);
            if (!mMtpDisabled) {
               addStorageDevicesLocked();
            }
            mServer.start();
        } else if (mServer != null && !isCurrentUser) {
            Log.d(TAG, "no longer current user; shutting down MTP server");
            // Internally, kernel will close our FD, and server thread will
            // handle cleanup.
            mServer = null;
            mDatabase.setServer(null);
        }
    }
    private void addStorageDevicesLocked() {
        if (mPtpMode) {
            // In PTP mode we support only primary storage
            final StorageVolume primary = StorageManager.getPrimaryVolume(mVolumes);
            final String path = primary.getPath();
            if (path != null) {
                String state = mStorageManager.getVolumeState(path);
                if (Environment.MEDIA_MOUNTED.equals(state)) {
                    addStorageLocked(mVolumeMap.get(path));
                }
            }
        } else {
            for (StorageVolume volume : mVolumeMap.values()) {
                addStorageLocked(volume);
            }
        }
    }



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值