Android USB Media Transfer Protocol(MPT)

1 minute read

Study USB MTP Device and Host mode in Android M.
Source Code Cross Reference: Android 6.0.1_r10

MTP Device Mode

Enable device mode:
Settings -> Developer options -> Select USB Configuration -> MTP
UsbDeviceManager: Setting USB config to mtp
device/lge/hammerhead/init.hammerhead.usb.rc : on property:sys.usb.config=mtp
system/core/rootdir/init.usb.configfs.rc: on property:sys.usb.config=mtp && property:sys.usb.configfs=1

USB plug to PC:
MtpReceiver: listen to android.hardware.usb.action.USB_STATE and bring up MtpService
UsbDeviceManager: get uevent USB_STATE=CONFIGURED from kernel
MtpService: create MtpDatabase MtpDatabase: create volume and storage path
MtpService: starting MTP server in MTP mode

Start transfer data to PC:
MtpDatabase: getObjectList storageID 65537 , formate 0 , parent -1
MtpDatabase: object_query to get object from media provider.

Handle UEVENT from Kernel, UsbHandler send MSG_UPDATE_STATE to UsbDeviceManager

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

handleUsbState start MTPService

packages/providers/MediaProvider/src/com/android/providers/media/MtpReceiver.java  

Set USB function: setCurrentFunction

frameworks/base/core/java/android/hardware/usb/UsbManager.java  

MTP Host Mode

UsbHostManager uses monitorUsbHostBus function to monitor usb’s event when system ready. monitorUsbHostBus is implemented at android_server_UsbHostManager_monitorUsbHostBus in JNI.

frameworks/base/services/usb/java/com/android/server/usb/UsbHostManager.java
frameworks/base/services/core/jni/com_android_server_UsbHostManager.cpp

After receiving USB attach event(ACTION_USB_DEVICE_ATTACHED) UsbHostManager adds an USB device via endUsbDeviceAdded() function, and deviceAttached() is called to figure out which activity should be lunched. Meanwhile, MtpClient will try to open MTP device use openDeviceLocked() function.

frameworks/base/services/usb/java/com/android/server/usb/UsbSettingsManager.java
packages/apps/Gallery2/src/com/android/gallery3d/data/MtpClient.java

In this case IngestActivity is selected from UsbSettingsManager::resolveActivity(). Because class is 6 and subclass is 1 in USB configuration that is matched in IngestActivity’s device_fileter.xml file.

packages/apps/Gallery2/res/xml/device_filter.xml

When IngestActivity is created, it will bind to IngestService which handled MTP protocol and provided MTP’s functionality.

packages/apps/Gallery2/src/com/android/gallery3d/ingest/IngestActivity.java
packages/apps/Gallery2/src/com/android/gallery3d/ingest/IngestService.java

MTP device detection issue in host mode

Android uses mClass, mSubclass, and mProtocal values in UsbInterface object to detect MTP devices.
For instance:

iPhone: UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=6,mSubclass=1,mProtocol=1  
Samsung: UsbInterface[mId=0,mAlternateSetting=0,mName=MTP,mClass=6,mSubclass=1,mProtocol=1  
Sony: UsbInterface[mId=0,mAlternateSetting=0,mName=MTP,mClass=255,mSubclass=255,mProtocol=0

The Sony cannot recognised as a MTP device.
We can modify MtpClient and device_filter.xml to fix this issue.

Relate source code

packages/providers/MediaProvider/src/com/android/providers/media/MtpReceiver.java  
packages/providers/MediaProvider/src/com/android/providers/media/MtpService.java  
packages/providers/MediaProvider/AndroidManifest.xml  
frameworks/base/services/usb/java/com/android/server/usb/  
frameworks/base/media/java/android/mtp/  
frameworks/base/media/jni/android_mtp_*  
frameworks/av/media/mtp/  
device/lge/hammerhead/init.hammerhead.usb.rc  
system/core/rootdir/init.usb.configfs.rc  

Leave a Comment