.netevent-handlingandroid-sourcemtpwpd

How do I generate custom MTP events from Android device (responder), and capture events in Windows (initiator)


What I need to do:

What I am using:

What I have working so far:

I have successful end to end communication between the initiator and the responder. I can send MTP commands and get MTP responses. I also successfully get standard event notifications from the responder.

The problem

I do not see MTP event codes in the USB packets coming from Android, even when the events are successfully fired and received by the initiator. When I change the standard event codes in Android to custom even codes, I still get the appropriate event messages (details below).

What I have done so far

On the responder side, when browsing through the Android source code, I found the MTP event codes defined in /frameworks/av/media/mtp/mtp.h.

The following are the eventIDs defined for adding/removing an object.

#define MTP_EVENT_OBJECT_ADDED                      0x4002
#define MTP_EVENT_OBJECT_REMOVED                    0x4003

These events codes are defined in the MTP specification.

For subscribing to the events on the initiator side, I am following the guidelines from the article here by Darene Lewis. I am using the GUIDs for the events from the constants defined here.

When a file is added to the device, or a file is removed from the device, the MTP event notification is fired, and the initiator gets the notification which maps the eventID to one of the constants. As I understand it, the first 4 bytes of the GUID corresponds to the eventID.

The following are the GUIDs for file added and removed events.

public static Guid WPD_EVENT_OBJECT_ADDED  = new Guid( 0xA726DA95, 0xE207, 0x4B02, 0x8D, 0x44, 0xBE, 0xF2, 0xE8, 0x6C, 0xBF, 0xFC  );        
public static Guid WPD_EVENT_OBJECT_REMOVED  = new Guid( 0xBE82AB88, 0xA52C, 0x4823, 0x96, 0xE5, 0xD0, 0x27, 0x26, 0x71, 0xFC, 0x38  );

My test consisted of adding/deleting files from the device.

When using the simulator, the initiator successfully gets the two event notifications, and they map to the correct WPD events as defined above. In addition, I confirmed that these event codes are shown in the USB packets.

When using the Android device, the initiator successfully gets the two event notifications, and they map to the correct WPD events as defined above. However, I do not see the event codes anywhere in the USB packets.

I do not understand how the COM interop library successfuly gets notified of the events, even though the packets do not show the MTP event codes.

Since I cannot see the event codes in the packet, I am unable to test sending custom event codes from the device to the initiator.

I did an experiment by modifying the above specified Android MTP event codes for vendor extension event codes (as mentioned in the MTP specification to be 0xC000 - 0xC7FF), and updating libmtp on the device to see what would happen.

I expected the initiator to never get the events, but surprisingly, even after changing the event codes, the COM interop library still received the events and mapped them to the correct GUIDs.

To summarize, when using Android, I do not see the MTP event codes in the USB messages, though the initiator somehow gets the notifications successfully. When using the MTP Simulator, I do see the MTP event codes in the USB messages.


Solution

  • I figured out the solution.

    It seems that when you perform event inducing actions using the OS (say, add/delete a file from the device using Windows Explorer), the event gets swallowed by the driver (WPD? USB?) though the event does get fired. Even when I used a hardware USB packet analyzer, I couldn't see the event packet. When I used the device itself to induce an event (MTP Simulator, BeagleBone Black with Android), the packets are clearly visible. I am not sure why not even the hardware analyzer displayed the event packet.

    To solve my problem (generating events), I created an overridden function in /frameworks/av/media/mtp/MtpServer.cpp, based on the sendEvent() function but with custom event codes, and it worked!