Android MTP之服务端UsbService启动 已经分析了mtp服务端的启动,本文来分析下切换mtp模式是如何实现的.
当点击usb通知的时候,会弹出一个usb功能选择界面,当选择File Transfer
,也就是mtp模式,会调用如下代码
mUsbManager = context.getSystemService(UsbManager.class);
mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MTP, true);
它会相应的调用服务端UsbService
的setCurrentFunction()
方法
public void setCurrentFunctions(long functions) {
// 需要声明权限
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
mDeviceManager.setCurrentFunctions(functions);
}
UsbService
把这个切换mtp的工作交给了UsbDeviceManager
,它会向自己(一个Handler)发送一个消息,然后调用setEnabledFunctions()
方法来处理
case MSG_SET_CURRENT_FUNCTIONS:
long functions = (Long) msg.obj;
setEnabledFunctions(functions, false);
Android MTP之服务端UsbService启动 说过,由于我的项目不支持hal层,因此setEnabledFunctions()
方法的实现类是UsbHandlerLegacy
protected void setEnabledFunctions(long usbFunctions, boolean forceRestart) {
// mtp, ptp模式,数据状态是解锁的
boolean usbDataUnlocked = isUsbDataTransferActive(usbFunctions);
// 如果数据解锁状态改变,就会更新usb通知
if (usbDataUnlocked != mUsbDataUnlocked) {
mUsbDataUnlocked = usbDataUnlocked;
pdateUsbNotification(false);
forceRestart = true;
}
// 首先保存旧状态,以免设置新功能失败后,可以回退
final long oldFunctions = mCurrentFunctions;
final boolean oldFunctionsApplied = mCurrentFunctionsApplied;
/**
* 设置新USB功能
*/
if (trySetEnabledFunctions(usbFunctions, forceRestart)) {
return;
}
/**
* 新USB功能设置失败,回退
*/
if (oldFunctionsApplied && oldFunctions != usbFunctions) {
if (trySetEnabledFunctions(oldFunctions, false)) {
return;
}
}
/**
* 回退还是失败,那就恢复默认USB功能
*/
if (trySetEnabledFunctions(UsbManager.FUNCTION_NONE, false)) {
return;
}
/**
* 恢复默认都失败了,最后再尝试一次
*/
if (trySetEnabledFunctions(UsbManager.FUNCTION_NONE, false)) {
return;
}
// Game over.
}
可以看出设置mtp模式的功能交给了trySetEnabledFunctions()
处理
private boolean trySetEnabledFunctions(long usbFunctions, boolean forceRestart) {
// ...
if ((!functions.equals(oemFunctions)
&& !mCurrentOemFunctions.equals(oemFunctions))
|| !mCurrentFunctionsStr.equals(functions)
|| !mCurrentFunctionsApplied
|| forceRestart) {
mCurrentFunctionsStr = functions;
mCurrentOemFunctions = oemFunctions;
mCurrentFunctionsApplied = false;
// 1.先关闭现在的usb功能
setUsbConfig(UsbManager.USB_FUNCTION_NONE);
// 如果设置失败就返回
if (!waitForState(UsbManager.USB_FUNCTION_NONE)) {
return false;
}
// 2.再设置新的usb功能
setUsbConfig(oemFunctions);
// 3. 如果usb状态改变就发送广播
if (mBootCompleted
&& (containsFunction(functions, UsbManager.USB_FUNCTION_MTP)
|| containsFunction(functions, UsbManager.USB_FUNCTION_PTP))) {
updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions));
}
// 如果失败就返回
if (!waitForState(oemFunctions)) {
return false;
}
mCurrentFunctionsApplied = true;
}
return true;
}
从这段代码,可以看出,成功设置一个usb功能,其实有两步
setUsbConfig()
设置usb功能.waitForState()
等待验证usb是否设置成功. private void setUsbConfig(String config) {
// 设置sys.usb.config
setSystemProperty(USB_CONFIG_PROPERTY, config);
}
private boolean waitForState(String state) {
String value = null;
// 最多等待1秒
for (int i = 0; i < 20; i++) {
// 获取sys.usb.state属性值
value = getSystemProperty(USB_STATE_PROPERTY, "");
if (state.equals(value)) return true;
SystemClock.sleep(50);
}
return false;
}
底层在检测到sys.usb.config
属性改变后,会启动对应的usb功能.以下代码截取自底层部分代码
on property:sys.usb.config=mtp,adb && property:sys.usb.configfs=0
# 先写0
write /sys/class/android_usb/android0/enable 0
# 写序列号
write /sys/class/android_usb/android0/iSerial ${ro.serialno}
# 写vid, pid
write /sys/class/android_usb/android0/idVendor 05C6
write /sys/class/android_usb/android0/idProduct 9039
# 设置USB功能为mtp,adb
write /sys/class/android_usb/android0/functions mtp,adb
# 再写1启动功能
write /sys/class/android_usb/android0/enable 1
# 启动adb
start adbd
# 设置 sys.usb.state属性值为sys.usb.config的属性值
setprop sys.usb.state ${sys.usb.config}
这段底层代码在检测到sys.usb.config
属性改变为mtp,adb
时,会设置usb功能为mtp, adb
,并且如果设置成功,就会把sys.usb.state
属性的值设置与sys.usb.config
一样.这个sys.usb.state
正好就是刚刚waitForState()
所使用的,它就是用来检测usb功能是否设置成功的标志.
假设现在已经成功切换到mtp模式,上层在trySetEnabledFunctions()
中还做了一件事,那就是使用updateUsbStateBroadcastIfNeeded()
发送usb状态改变的广播.
protected void updateUsbStateBroadcastIfNeeded(long functions) {
// send a sticky broadcast containing current USB state
Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
| Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(UsbManager.USB_CONNECTED, mConnected);
intent.putExtra(UsbManager.USB_HOST_CONNECTED, mHostConnected);
intent.putExtra(UsbManager.USB_CONFIGURED, mConfigured);
intent.putExtra(UsbManager.USB_DATA_UNLOCKED,
isUsbTransferAllowed() && isUsbDataTransferActive(mCurrentFunctions));
long remainingFunctions = functions;
while (remainingFunctions != 0) {
intent.putExtra(UsbManager.usbFunctionsToString(
Long.highestOneBit(remainingFunctions)), true);
remainingFunctions -= Long.highestOneBit(remainingFunctions);
}
// 状态没改变就不发送广播
if (!isUsbStateChanged(intent)) {
return;
}
// 发送一个sticky类型的广播
sendStickyBroadcast(intent);
mBroadcastedIntent = intent;
}
那么,谁接收这个广播,接收这个广播又干了什么呢,在下一篇文章揭晓.