Platform: RK3399
OS: industry-71
客户反馈使用他们的usb身份证模块上电之后,usbmanager.getDeviceList获取异常.具体的测试流程是
客户流程:插着Usb身份证模块上电,getDeviceList获取设备个数为1,拔出身份证模块后,getDeviceList获取设备个数为0;再次接入身份证模块,getDeviceList获取设备个数为0;插上U盘,getDeviceList获取设备个数为0
实测:插着身份证模块上电后getDeviceList为1.此时插入u盘,getDeviceList仍为1.
发现只要插着身份证模块上电,后续的usb插入拔出,getDeviceList获取的数值都是异常
查看插入u盘时的log,发现
01-18 09:39:17.787 486 809 E UsbHostManager: mNewDevice is not null in endUsbDeviceAdded
查看对应的代码,发现添加设备流程是在beginUsbDeviceAdded中new 一个mNewDevice,当设备添加完成后会在endUsbDeviceAdded释放
//frameworks/base/services/usb/java/com/android/server/usb/UsbHostManager.java
//开始添加设备
private boolean beginUsbDeviceAdded(String deviceName, int vendorID, int productID,
int deviceClass, int deviceSubclass, int deviceProtocol,
String manufacturerName, String productName, int version, String serialNumber) {
if (DEBUG) {
Slog.d(TAG, "usb:UsbHostManager.beginUsbDeviceAdded(" + deviceName + ")");
// Audio Class Codes:
// Audio: 0x01
// Audio Subclass Codes:
// undefined: 0x00
// audio control: 0x01
// audio streaming: 0x02
// midi streaming: 0x03
// some useful debugging info
Slog.d(TAG, "usb: nm:" + deviceName + " vnd:" + vendorID + " prd:" + productID + " cls:"
+ deviceClass + " sub:" + deviceSubclass + " proto:" + deviceProtocol);
}
// OK this is non-obvious, but true. One can't tell if the device being attached is even
// potentially an audio device without parsing the interface descriptors, so punt on any
// such test until endUsbDeviceAdded() when we have that info.
if (isBlackListed(deviceName) ||
isBlackListed(deviceClass, deviceSubclass, deviceProtocol)) {
return false;
}
synchronized (mLock) {
if (mDevices.get(deviceName) != null) {
Slog.w(TAG, "device already on mDevices list: " + deviceName);
return false;
}
if (mNewDevice != null) {
Slog.e(TAG, "mNewDevice is not null in endUsbDeviceAdded");
return false;
}
// Create version string in "%.%" format
String versionString = Integer.toString(version >> 8) + "." + (version & 0xFF);
mNewDevice = new UsbDevice(deviceName, vendorID, productID,
deviceClass, deviceSubclass, deviceProtocol,
manufacturerName, productName, versionString, serialNumber);
mNewConfigurations = new ArrayList<UsbConfiguration>();
mNewInterfaces = new ArrayList<UsbInterface>();
mNewEndpoints = new ArrayList<UsbEndpoint>();
}
return true;
}
//结束添加设备
private void endUsbDeviceAdded() {
if (DEBUG) {
Slog.d(TAG, "usb:UsbHostManager.endUsbDeviceAdded()");
}
if (mNewInterface != null) {
mNewInterface.setEndpoints(
mNewEndpoints.toArray(new UsbEndpoint[mNewEndpoints.size()]));
}
if (mNewConfiguration != null) {
mNewConfiguration.setInterfaces(
mNewInterfaces.toArray(new UsbInterface[mNewInterfaces.size()]));
}
synchronized (mLock) {
if (mNewDevice != null) {
mNewDevice.setConfigurations(
mNewConfigurations.toArray(new UsbConfiguration[mNewConfigurations.size()]));
mDevices.put(mNewDevice.getDeviceName(), mNewDevice);
Slog.d(TAG, "Added device " + mNewDevice);
getCurrentSettings().deviceAttached(mNewDevice);
mUsbAlsaManager.usbDeviceAdded(mNewDevice);
checkUsbCameraStatus(mNewDevice, true);
} else {
Slog.e(TAG, "mNewDevice is null in endUsbDeviceAdded");
}
mNewDevice = null;
mNewConfigurations = null;
mNewInterfaces = null;
mNewEndpoints = null;
mNewConfiguration = null;
mNewInterface = null;
}
}
而从log mNewDevice is not null in endUsbDeviceAdded可知,U盘无法加载的原因是前一个usb设备(身份证模块)在加载时可能出现问题,没有在endUsbDeviceAdded释放mNewDevice,导致U盘没有添加到usbmanager.getDeviceList中
继续查找log,发现插着身份证模块开机时有如下log
01-18 09:51:53.561 488 801 E UsbHostManagerJNI: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.String.toLowerCase()' on a null object reference
01-18 09:51:53.561 488 801 E UsbHostManagerJNI: at com.android.server.usb.UsbHostManager.checkUsbCameraStatus(UsbHostManager.java:263)
01-18 09:51:53.561 488 801 E UsbHostManagerJNI: at com.android.server.usb.UsbHostManager.endUsbDeviceAdded(UsbHostManager.java:233)
01-18 09:51:53.561 488 801 E UsbHostManagerJNI: at com.android.server.usb.UsbHostManager.monitorUsbHostBus(Native Method)
01-18 09:51:53.561 488 801 E UsbHostManagerJNI: at com.android.server.usb.UsbHostManager.-wrap0(UsbHostManager.java)
01-18 09:51:53.561 488 801 E UsbHostManagerJNI: at com.android.server.usb.UsbHostManager$1.run(UsbHostManager.java:315)
01-18 09:51:53.561 488 801 E UsbHostManagerJNI: at java.lang.Thread.run(Thread.java:761)
01-18 09:51:53.561 488 801 D UsbHostManager: usb:UsbHostManager.beginUsbDeviceAdded(/dev/bus/usb/007/001)
01-18 09:51:53.561 488 801 D UsbHostManager: usb: nm:/dev/bus/usb/007/001 vnd:7531 prd:2 cls:9 sub:0 proto:1
01-18 09:51:53.562 488 801 D UsbHostManager: usb:UsbHostManager.beginUsbDeviceAdded(/dev/bus/usb/001/001)
01-18 09:51:53.562 488 801 D UsbHostManager: usb: nm:/dev/bus/usb/001/001 vnd:7531 prd:2 cls:9 sub:0 proto:0
查看对应代码,发现是rk在这里添加了一个usb类型检测的代码,用于热拔插usb摄像头的处理,但是没有考虑productname为null的情况,导致抛空出错
private void checkUsbCameraStatus(UsbDevice device, boolean added) {
if (device != null && !mBootCompleted) {
String devicename = device.getDeviceName();
String productname = device.getProductName();
if( productname.toLowerCase().contains("wlan")) //263行
{
//For ROC+ Usb Wlan Error Detech
Slog.d(TAG,"This is Usb Wlan");
Slog.d(TAG,"WLAN Devicename = "+devicename);
Slog.d(TAG,"WLAN Productname = "+productname);
return ;
}
添加productname != null 判断后,编译固件测试正常
diff --git a/frameworks/base/services/usb/java/com/android/server/usb/UsbHostManager.java b/frameworks/base/services/usb/java/com/android/server/usb/UsbHostManager.java
index 083eeaa..9ac1fb1 100644
--- a/frameworks/base/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/frameworks/base/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -260,7 +260,7 @@ public class UsbHostManager {
if (device != null && !mBootCompleted) {
String devicename = device.getDeviceName();
String productname = device.getProductName();
- if(productname.toLowerCase().contains("wlan"))
+ if(productname != null && productname.toLowerCase().contains("wlan"))
{
//For ROC+ Usb Wlan Error Detech
Slog.d(TAG,"This is Usb Wlan");