USB(通用串行总线)主机模式向外设进行供电,使 Android 设备能够驱动 USB 总线,并且可以使用各种 USB 外设(包括音频接口,存储,MIDI),USB 和蓝牙低功耗连接都可以用于传输 MIDI 协议。USB配件模式,受外设供电驱动,包括数据传输,充电。USB开发模式,应用调试,唯一可见的外设功能是 Android fastboot 或 Android 调试桥 (adb)。fastboot 和 adb 协议所在层高于 USB 批量数据传输模式所在层。
Android 平台支持使用即插即用的 USB 摄像头(例如网络摄像头),但前提是这些摄像头采用标准的 Android Camera2 API 和摄像头 HIDL 接口,全新的 USB 摄像头 HAL 进程是外接摄像头提供程序的一部分,该提供程序会监听 USB 设备可用性,并相应地枚举外接摄像头设备。该进程具有与内置摄像头 HAL 进程类似的权限和 SE 策略。直接与 USB 设备通信的第三方网络摄像头应用访问 UVC 设备时所需的摄像头权限与所有常规摄像头应用所需的权限相同。
frameworks\base\services\usb\java\com\android\server\usb\UsbService.java
public static class Lifecycle extends SystemService {
private UsbService mUsbService;
......
@Override
public void onStart() { mUsbService = new UsbService(getContext());} //USB服务初始化
@Override
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
mUsbService.systemReady(); //系统准备就绪
} else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
mUsbService.bootCompleted();//系统启动完成
}
}
......
}
frameworks\base\services\usb\java\com\android\server\usb\UsbService.java
初始化USB服务
public UsbService(Context context) {
mContext = context;
//多用户管理
mUserManager = context.getSystemService(UserManager.class);
//用户管理设置
mSettingsManager = new UsbSettingsManager(context);
//高级音频管理
mAlsaManager = new UsbAlsaManager(context);
//包管理
final PackageManager pm = mContext.getPackageManager();
//USB主机模式
if (pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
mHostManager = new UsbHostManager(context, mAlsaManager, mSettingsManager);
}
//USB设备管理
if (new File("/sys/class/android_usb").exists()) {
mDeviceManager = new UsbDeviceManager(context, mAlsaManager, mSettingsManager);
}
//USB端口管理
if (mHostManager != null || mDeviceManager != null) {
mPortManager = new UsbPortManager(context);
}
//切换为系统用户
onSwitchUser(UserHandle.USER_SYSTEM);
//注册设备代理管理
final IntentFilter filter = new IntentFilter();
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
mContext.registerReceiver(mReceiver, filter, null, null);
}
frameworks\base\services\usb\java\com\android\server\usb\UsbService.java
public void systemReady() {
mAlsaManager.systemReady();
if (mDeviceManager != null) {
mDeviceManager.systemReady();
}
if (mHostManager != null) {
mHostManager.systemReady();
}
if (mPortManager != null) {
mPortManager.systemReady();
}
}
frameworks\base\services\usb\java\com\android\server\usb\UsbAlsaManager.java
frameworks\base\services\usb\java\com\android\server\usb\UsbDeviceManager.java
frameworks\base\services\usb\java\com\android\server\usb\UsbHostManager.java
frameworks\base\services\usb\java\com\android\server\usb\UsbPortManager.java
//系统音频服务
public void systemReady() {
mAudioService = IAudioService.Stub.asInterface(
ServiceManager.getService(Context.AUDIO_SERVICE));
mAlsaObserver.startWatching(); //开始高级音频监听
......
}
//创建USB设备Notification
public void systemReady() {
mNotificationManager = (NotificationManager)
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
// Ensure that the notification channels are set up
if (isTv()) {
// TV-specific notification channel
mNotificationManager.createNotificationChannel(
new NotificationChannel(ADB_NOTIFICATION_CHANNEL_ID_TV,
mContext.getString(
com.android.internal.R.string
.adb_debugging_notification_channel_tv),
NotificationManager.IMPORTANCE_HIGH));
}
......
mHandler.sendEmptyMessage(MSG_SYSTEM_READY);
}
//启动USB主机模式总线
public void systemReady() {
synchronized (mLock) {
// Create a thread to call into native code to wait for USB host events.
// This thread will call us back on usbDeviceAdded and usbDeviceRemoved.
Runnable runnable = new Runnable() {
public void run() {
monitorUsbHostBus();
}
};
new Thread(null, runnable, "UsbService host thread").start();
}
}
//查询USB设备端口转状态
public void systemReady() {
if (mProxy != null) {
try {
mProxy.queryPortStatus();
} catch (RemoteException e) {
.......
}
}
mSystemReady = true;
}
frameworks\base\core\java\android\hardware\usb\UsbManager.java
public UsbDeviceConnection openDevice(UsbDevice device) {
try {
String deviceName = device.getDeviceName();
//打开USB设备,返回文件描述符FD
ParcelFileDescriptor pfd = mService.openDevice(deviceName);
if (pfd != null) {
//创建Socket连接通道,用于数据指令传输
UsbDeviceConnection connection = new UsbDeviceConnection(device);
boolean result = connection.open(deviceName, pfd, mContext);
pfd.close();
if (result) {
return connection;
}
}
} catch (Exception e) {
Log.e(TAG, "exception in UsbManager.openDevice", e);
}
return null;
}
frameworks\base\services\usb\java\com\android\server\usb\UsbService.java
/* Opens the specified USB device (host mode) */
@Override
public ParcelFileDescriptor openDevice(String deviceName) {
ParcelFileDescriptor fd = null;
if (mHostManager != null) {
synchronized (mLock) {
if (deviceName != null) {
int userIdInt = UserHandle.getCallingUserId();
boolean isCurrentUser = isCallerInCurrentUserProfileGroupLocked();
//以主机模式打开制定USB
if (isCurrentUser) {
fd = mHostManager.openDevice(deviceName, getSettingsForUser(userIdInt));
} else {
Slog.w(TAG, "Cannot open " + deviceName + " for user " + userIdInt +
" as user is not active.");
}
}
}
}
return fd;
}
frameworks\base\services\usb\java\com\android\server\usb\UsbHostManager.java
/* Opens the specified USB device */
public ParcelFileDescriptor openDevice(String deviceName, UsbUserSettingsManager settings) {
synchronized (mLock) {
if (isBlackListed(deviceName)) {
throw new SecurityException("USB device is on a restricted bus");
}
//从已存在的USB设备列表中查找一个
UsbDevice device = mDevices.get(deviceName);
......
settings.checkPermission(device);
return nativeOpenDevice(deviceName);
}
}
frameworks\base\services\core\jni\com_android_server_UsbHostManager.cpp
static jobject android_server_UsbHostManager_openDevice(JNIEnv *env, jobject /* thiz */,
jstring deviceName)
{
const char *deviceNameStr = env->GetStringUTFChars(deviceName, NULL);
//调用系统提供的USB设备打开函数
struct usb_device* device = usb_device_open(deviceNameStr);
env->ReleaseStringUTFChars(deviceName, deviceNameStr);
//获得USB设备的文件描述符
int fd = usb_device_get_fd(device);
if (fd < 0) {
usb_device_close(device);
return NULL;
}
int newFD = dup(fd);
usb_device_close(device);
jobject fileDescriptor = jniCreateFileDescriptor(env, newFD);
if (fileDescriptor == NULL) {
return NULL;
}
return env->NewObject(gParcelFileDescriptorOffsets.mClass,
gParcelFileDescriptorOffsets.mConstructor, fileDescriptor);
}
system\core\libusbhost\usbhost.c
struct usb_device *usb_device_open(const char *dev_name)
{
int fd, did_retry = 0, writeable = 1;
D("usb_device_open %s\n", dev_name);
retry:
fd = open(dev_name, O_RDWR); //打开设备
if (fd < 0) {
/* if we fail, see if have read-only access */
//失败则以只读模式打开
fd = open(dev_name, O_RDONLY);
D("usb_device_open open returned %d errno %d\n", fd, errno);
if (fd < 0 && (errno == EACCES || errno == ENOENT) && !did_retry) {
/* work around race condition between inotify and permissions management */
sleep(1);
did_retry = 1;
goto retry;
}
if (fd < 0)
return NULL;
writeable = 0;
D("[ usb open read-only %s fd = %d]\n", dev_name, fd);
}
//新建一个USB设备
struct usb_device* result = usb_device_new(dev_name, fd);
if (result)
result->writeable = writeable;
return result;
}
system\core\libusbhost\usbhost.c
struct usb_device *usb_device_new(const char *dev_name, int fd)
{
struct usb_device *device = calloc(1, sizeof(struct usb_device)); //分配内存
int length;
D("usb_device_new %s fd: %d\n", dev_name, fd);
if (lseek(fd, 0, SEEK_SET) != 0)
goto failed;
length = read(fd, device->desc, sizeof(device->desc)); //读取设备描述符长度
D("usb_device_new read returned %d errno %d\n", length, errno);
if (length < 0)
goto failed;
strncpy(device->dev_name, dev_name, sizeof(device->dev_name) - 1);
device->fd = fd;
device->desc_length = length;
// assume we are writeable, since usb_device_get_fd will only return writeable fds
device->writeable = 1;
return device;
failed:
close(fd);
free(device);
return NULL;
}
frameworks\base\core\java\android\hardware\usb\UsbDeviceConnection.java
public UsbDeviceConnection(UsbDevice device) {
mDevice = device;
}
/* package */ boolean open(String name, ParcelFileDescriptor pfd, @NonNull Context context) {
mContext = context.getApplicationContext();
boolean wasOpened = native_open(name, pfd.getFileDescriptor());
......
return wasOpened;
}
frameworks\base\core\jni\android_hardware_UsbDeviceConnection.cpp
调用JNI层打开指定的USB设备
static jboolean
android_hardware_UsbDeviceConnection_open(JNIEnv *env, jobject thiz, jstring deviceName,
jobject fileDescriptor)
{
int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
// duplicate the file descriptor, since ParcelFileDescriptor will eventually close its copy
fd = dup(fd);
if (fd < 0)
return JNI_FALSE;
const char *deviceNameStr = env->GetStringUTFChars(deviceName, NULL);
struct usb_device* device = usb_device_new(deviceNameStr, fd); //新建
if (device) {
env->SetLongField(thiz, field_context, (jlong)device);
} else {
ALOGE("usb_device_open failed for %s", deviceNameStr);
close(fd);
}
env->ReleaseStringUTFChars(deviceName, deviceNameStr);
return (device != NULL) ? JNI_TRUE : JNI_FALSE;
}
frameworks\base\services\usb\java\com\android\server\usb\UsbPortManager.java
设备端口管理
public UsbPortManager(Context context) {
mContext = context;
try {
//HIDL层的Service
boolean ret = IServiceManager.getService()
.registerForNotifications("[email protected]::IUsb",
"", mServiceNotification);
......
} catch (RemoteException e) {
......
return;
}
connectToProxy(null);
}
frameworks\base\services\usb\java\com\android\server\usb\UsbPortManager.java
private void connectToProxy(IndentingPrintWriter pw) {
synchronized (mLock) {
try {
//获取HIDL服务
mProxy = IUsb.getService();
mProxy.linkToDeath(new DeathRecipient(pw), USB_HAL_DEATH_COOKIE);
//设置回调,一会儿再回头看
mProxy.setCallback(mHALCallback);
mProxy.queryPortStatus();
} catch (NoSuchElementException e) {
......
}
}
}
hardware\interfaces\usb\1.0\default\Usb.cpp
Return<void> Usb::setCallback(const sp<IUsbCallback>& callback) {
pthread_mutex_lock(&mLock);
if ((mCallback == NULL && callback == NULL) ||
(mCallback != NULL && callback != NULL)) {
mCallback = callback;
pthread_mutex_unlock(&mLock);
return Void();
}
......
destroyThread = false;
signal(SIGUSR1, sighandler);
//创建线程,运行work
if (pthread_create(&mPoll, NULL, work, this)) {
ALOGE("pthread creation failed %d", errno);
mCallback = NULL;
}
pthread_mutex_unlock(&mLock);
return Void();
}
hardware\interfaces\usb\1.0\default\Usb.cpp
使用EPOLL,UEVENT机制,多路IO阻塞复用
void* work(void* param) {
int epoll_fd, uevent_fd;
struct epoll_event ev;
int nevents = 0;
struct data payload;
uevent_fd = uevent_open_socket(64*1024, true); //创建套接
//payload是个转换结构体
payload.uevent_fd = uevent_fd;
payload.usb = (android::hardware::usb::V1_0::implementation::Usb *)param;
fcntl(uevent_fd, F_SETFL, O_NONBLOCK);
ev.events = EPOLLIN;
//绑定事件处理函数uevent_event
ev.data.ptr = (void *)uevent_event;
epoll_fd = epoll_create(64);
//循环等待UEVENT事件
while (!destroyThread) {
struct epoll_event events[64];
nevents = epoll_wait(epoll_fd, events, 64, -1);
for (int n = 0; n < nevents; ++n) {
if (events[n].data.ptr)
(*(void (*)(int, struct data *payload))events[n].data.ptr)
(events[n].events, &payload);
}
}
}
hardware\interfaces\usb\1.0\default\Usb.cpp
处理来自内核的USB驱动事件
static void uevent_event(uint32_t /*epevents*/, struct data *payload) {
char msg[UEVENT_MSG_LEN + 2];
char *cp;
int n;
n = uevent_kernel_multicast_recv(payload->uevent_fd, msg, UEVENT_MSG_LEN);
if (n <= 0)
return;
if (n >= UEVENT_MSG_LEN) /* overflow -- discard */
return;
msg[n] = '\0';
msg[n + 1] = '\0';
cp = msg;
//如果有数据,继续处理
while (*cp) {
if (!strcmp(cp, "SUBSYSTEM=dual_role_usb")) {
ALOGE("uevent received %s", cp);
if (payload->usb->mCallback != NULL) {
hidl_vec<PortStatus> currentPortStatus;
Status status = getPortStatusHelper(currentPortStatus);
//执行上层的回调
Return<void> ret =
payload->usb->mCallback->notifyPortStatusChange(currentPortStatus, status);
}
break;
}
/* advance to after the next \0 */
while (*cp++);
}
}
frameworks\base\services\usb\java\com\android\server\usb\UsbPortManager.java
现在我们来看看刚刚的遇到的mHALCallback
private static class HALCallback extends IUsbCallback.Stub {
public IndentingPrintWriter pw;
public UsbPortManager portManager;
.......
public void notifyPortStatusChange(ArrayList<PortStatus> currentPortStatus, int retval) {
ArrayList<RawPortInfo> newPortInfo = new ArrayList<RawPortInfo>();
//处理USB端口状态
for (PortStatus current : currentPortStatus) {
RawPortInfo temp = new RawPortInfo(current.portName,
current.supportedModes, current.currentMode,
current.canChangeMode, current.currentPowerRole,
current.canChangePowerRole,
current.currentDataRole, current.canChangeDataRole);
newPortInfo.add(temp);
logAndPrint(Log.INFO, pw, "ClientCallback: " + current.portName);
}
//转给UsbPortManager的Handler来处理
Message message = portManager.mHandler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putParcelableArrayList(PORT_INFO, newPortInfo);
message.what = MSG_UPDATE_PORTS;
message.setData(bundle);
portManager.mHandler.sendMessage(message);
return;
}
......
};
frameworks\base\services\usb\java\com\android\server\usb\UsbPortManager.java
private final Handler mHandler = new Handler(FgThread.get().getLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_UPDATE_PORTS: {
Bundle b = msg.getData();
ArrayList<RawPortInfo> PortInfo = b.getParcelableArrayList(PORT_INFO);
synchronized (mLock) {
updatePortsLocked(null, PortInfo);
}
break;
}
}
}
};
frameworks\base\services\usb\java\com\android\server\usb\UsbPortManager.java
private void updatePortsLocked(IndentingPrintWriter pw, ArrayList<RawPortInfo> newPortInfo) {
//处理USB设备的插入删除移除
// Process the updates.
// Once finished, the list of ports will only contain ports in DISPOSITION_READY.
for (int i = mPorts.size(); i-- > 0; ) {
final PortInfo portInfo = mPorts.valueAt(i);
switch (portInfo.mDisposition) {
case PortInfo.DISPOSITION_ADDED:
handlePortAddedLocked(portInfo, pw);
portInfo.mDisposition = PortInfo.DISPOSITION_READY;
break;
case PortInfo.DISPOSITION_CHANGED:
handlePortChangedLocked(portInfo, pw);
portInfo.mDisposition = PortInfo.DISPOSITION_READY;
break;
case PortInfo.DISPOSITION_REMOVED:
mPorts.removeAt(i);
portInfo.mUsbPortStatus = null; // must do this early
handlePortRemovedLocked(portInfo, pw);
break;
}
}
}
frameworks\base\services\usb\java\com\android\server\usb\UsbPortManager.java
终于发送了一个广播将端口状态信息发送出去
private void sendPortChangedBroadcastLocked(PortInfo portInfo) {
final Intent intent = new Intent(UsbManager.ACTION_USB_PORT_CHANGED);
intent.addFlags(
Intent.FLAG_RECEIVER_FOREGROUND |
Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
intent.putExtra(UsbManager.EXTRA_PORT, portInfo.mUsbPort);
intent.putExtra(UsbManager.EXTRA_PORT_STATUS, portInfo.mUsbPortStatus);
// Guard against possible reentrance by posting the broadcast from the handler
// instead of from within the critical section.
mHandler.post(new Runnable() {
@Override
public void run() {
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
}
});
}
frameworks\base\services\usb\java\com\android\server\usb\UsbDeviceManager.java
public UsbDeviceManager(Context context, UsbAlsaManager alsaManager,
UsbSettingsManager settingsManager) {
//USB配件模式检查
mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
if (nativeIsStartRequested()) {
if (DEBUG) Slog.d(TAG, "accessory attached at boot");
startAccessoryMode();
}
mHandler = new UsbHandler(FgThread.get().getLooper());
//开发人员adb调试是否打开
boolean secureAdbEnabled = SystemProperties.getBoolean("ro.adb.secure", false);
boolean dataEncrypted = "1".equals(SystemProperties.get("vold.decrypt"));
if (secureAdbEnabled && !dataEncrypted) {
mDebuggingManager = new UsbDebuggingManager(context); //usb调试管理
}
//对应上面发送的广播
mContext.registerReceiver(mHostReceiver,
new IntentFilter(UsbManager.ACTION_USB_PORT_CHANGED));
mContext.registerReceiver(mChargingReceiver,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
}
frameworks\base\services\usb\java\com\android\server\usb\UsbDeviceManager.java
监听消息转发处理事务
//adb调试模式开关监听
private class AdbSettingsObserver extends ContentObserver {
public AdbSettingsObserver() {
super(null);
}
@Override
public void onChange(boolean selfChange) {
boolean enable = (Settings.Global.getInt(mContentResolver,
Settings.Global.ADB_ENABLED, 0) > 0);
mHandler.sendMessage(MSG_ENABLE_ADB, enable);
}
}
//监听来自内核的Uevent
private final UEventObserver mUEventObserver = new UEventObserver() {
@Override
public void onUEvent(UEventObserver.UEvent event) {
if (DEBUG) Slog.v(TAG, "USB UEVENT: " + event.toString());
String state = event.get("USB_STATE");
String accessory = event.get("ACCESSORY");
if (state != null) {
mHandler.updateState(state);
} else if ("START".equals(accessory)) {
if (DEBUG) Slog.d(TAG, "got accessory start");
startAccessoryMode();
}
}
};
//接收USB状态变化
private final BroadcastReceiver mHostReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
UsbPort port = intent.getParcelableExtra(UsbManager.EXTRA_PORT);
UsbPortStatus status = intent.getParcelableExtra(UsbManager.EXTRA_PORT_STATUS);
mHandler.updateHostState(port, status); //交给内部Handler处理,不再深入了
}
};
//接受USB拔插状态
private final BroadcastReceiver mChargingReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharging = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
mHandler.sendMessage(MSG_UPDATE_CHARGING_STATE, usbCharging);
}
};
最后在UsbHandler里处理包括MIDI,主机/配件模式,音频,adb调试,状态Notification,设备的增减状态变化等事务。具体就不再细究了,以后遇到再分析。