如何从 Android 设备(响应者)生成自定义 MTP 事件,并在 Windows(发起者)中捕获事件

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

我需要做的事情:

我用的是:

我目前的工作:

我在发起者和响应者之间进行了成功的端到端通信。我可以发送 MTP 命令并获得 MTP 响应。我也成功地从响应者那里获得了标准事件通知。

问题

我在来自 Android 的 USB 数据包中没有看到 MTP 事件代码,即使事件已成功触发并被启动器接收。当我将 Android 中的标准事件代码更改为自定义偶数代码时,我仍然会收到相应的事件消息(详情如下)。

到目前为止我做了什么

在响应端,浏览Android源代码时,发现在/frameworks/av/media/mtp/mtp.h.[=中定义了MTP事件代码15=]

以下是为 adding/removing 对象定义的事件 ID。

#define MTP_EVENT_OBJECT_ADDED                      0x4002
#define MTP_EVENT_OBJECT_REMOVED                    0x4003

这些事件代码在 MTP 规范中定义。

为了订阅发起方的事件,我遵循文章 here by Darene Lewis. I am using the GUIDs for the events from the constants defined here 中的指南。

当文件添加到设备或从设备中删除文件时,会触发 MTP 事件通知,发起者会收到将 eventID 映射到常量之一的通知。据我了解,GUID的前4个字节对应于eventID。

以下是文件添加和删除事件的 GUID。

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  );

我的测试包含来自设备的 adding/deleting 个文件。

使用模拟器时,发起者成功获取了两个事件通知,并且它们映射到上面定义的正确 WPD 事件。此外,我确认这些事件代码显示在 USB 数据包中。

当使用 Android 设备时,发起者成功获得两个事件通知,并且它们映射到正确的 WPD 事件,如上定义。但是,我在 USB 数据包中的任何地方都看不到事件代码。

我不明白 COM 互操作库如何成功收到事件通知,即使数据包不显示 MTP 事件代码。

因为我看不到数据包中的事件代码,所以我无法测试从设备向发起者发送自定义事件代码。

我通过修改上面指定的 Android MTP 事件代码为供应商扩展事件代码(如 MTP 规范中所述为 0xC000 - 0xC7FF)进行了实验,并更新了设备上的 libmtp 以查看什么会发生的。

我预计发起者永远不会收到事件,但令人惊讶的是,即使在更改事件代码之后,COM 互操作库仍然收到事件并将它们映射到正确的 GUID。

总而言之,在使用 Android 时,我 没有 在 USB 消息中看到 MTP 事件代码,尽管启动器以某种方式成功地获得了通知。使用 MTP 模拟器时,我确实在 USB 消息中看到了 MTP 事件代码。

我想出了解决办法。

似乎当您使用 OS(例如,add/delete 来自使用 Windows Explorer 的设备的文件)执行事件诱导操作时,事件被驱动程序吞没(WPD?USB?)虽然事件确实被触发了。即使当我使用硬件 USB 数据包分析器时,我也看不到事件数据包。当我使用设备本身引发事件时(MTP 模拟器,带有 Android 的 BeagleBone Black),数据包清晰可见。我不确定为什么连硬件分析器都不显示事件包。

为了解决我的问题(生成事件),我在 /frameworks/av/media/mtp/MtpServer.cpp 中创建了一个基于 sendEvent() 函数但使用自定义事件代码的覆盖函数, 它奏效了!