USB (Universal Serial Bus) host mode provides power to peripherals, enabling Android devices to drive the USB bus, and can use a variety of USB peripherals (including audio interfaces, storage, MIDI), both USB and Bluetooth low energy connections Used to transmit MIDI protocol. USB accessory mode, driven by peripheral power supply, including data transmission and charging. USB development mode, application debugging, the only visible peripheral function is Android fastboot or Android debug bridge (adb). The layers of fastboot and adb protocols are higher than those of USB bulk data transfer mode.
The Android platform supports the use of plug-and-play USB cameras (such as webcams), but only if these cameras use the standard Android Camera2 API and camera HIDL interface, the new USB camera HAL process is part of the external camera provider, the provider Listens for USB device availability and enumerates external camera devices accordingly. This process has similar permissions and SE policies as the built-in camera HAL process. Third-party webcam apps that communicate directly with USB devices require the same camera permissions as all regular camera apps to access UVC devices.
1. Usb service starts
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 service initialization @Override public void onBootPhase(int phase) { if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) { mUsbService.systemReady(); //system is ready } else if (phase == SystemService.PHASE_BOOT_COMPLETED) { mUsbService.bootCompleted();//system boot completed } } ... ... } 1 2 3 4 5
6
7
8
9
10
11
12
13
14
15
frameworks\base\services\usb\java\com\android\server\usb\UsbService.java
initializes USB service
public UsbService(Context context) { mContext = context; //multi-user management mUserManager = context.getSystemService(UserManager.class); //user management settings mSettingsManager = new UsbSettingsManager(context); //advanced audio management mAlsaManager = new UsbAlsaManager( context); //package management final PackageManager pm = mContext.getPackageManager(); //USB host mode if (pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) { mHostManager = new UsbHostManager(context, mAlsaManager, mSettingsManager); } //USB Device management if (new File("/sys/class/android_usb").exists()) {
mDeviceManager = new UsbDeviceManager(context, mAlsaManager, mSettingsManager);
}
//USB port management
if (mHostManager != null || mDeviceManager != null) { mPortManager = new UsbPortManager(context); } //Switch to system user onSwitchUser(UserHandle .USER_SYSTEM); //Register device agent management final IntentFilter filter = new IntentFilter(); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); mContext.register Receiver(mReceiver, filter, null, null); } 1 2 3 4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
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
//System audio service
public void systemReady() { mAudioService = IAudioService.Stub.asInterface( ServiceManager.getService(Context.AUDIO_SERVICE)); mAlsaObserver.startWatching(); //Start advanced audio monitoring ... } // Create USB device 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();
}
}
//Query the USB device port transfer status
public void systemReady() { if (mProxy != null) { try { mProxy.queryPortStatus(); } catch (RemoteException e) { ....... } } mSystemReady = true; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
29
30
31 32
33
34
35 36
37 38 39
40
41 42 43 44 45 46 47 48 49 50 51 2. USB device open frameworks
\ base\core\java\android\hardware\ usb \UsbManager.java
public UsbDeviceConnection openDevice(UsbDevice device) { try { String deviceName = device.getDeviceName(); //Open the USB device and return the file descriptor FD ParcelFileDescriptor pfd = mService.openDevice(deviceName); if (pfd != null) { // Create a Socket connection channel for data instruction transmission 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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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"); } / / Find a UsbDevice from the list of existing USB devices device = mDevices.get(deviceName); ...... settings.checkPermission(device); return nativeOpenDevice(deviceName); } } 1 2 3 4 5 6 7 8 9 10
11
12
13
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); //Call the USB device open function provided by the system struct usb_device* device = usb_de vice_open (deviceNameStr); env->ReleaseStringUTFChars(deviceName, deviceNameStr); //Get the file descriptor of the USB device 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);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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;
}
1
2
3
4
5
6
7
8
9
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;
}
1
2
3
4
5
6
7
8
9 10
11
12 13 14 15 16 17 18 19 20 21 22 3. USB device detection frameworks\base\services\usb\java\com\android\server\usb\UsbPortManager.java device port management
public UsbPortManager(Context context) {
mContext = context;
try {
//HIDL层的Service
boolean ret = IServiceManager.getService()
.registerForNotifications("[email protected]::IUsb",
"", mServiceNotification);
......
} catch (RemoteException e) {
......
return;
}
connectToProxy(null);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
frameworks\base\services\usb\java\com\android\server\usb\UsbPortManager.java
private void connectToProxy(IndentingPrintWriter pw) { synchronized (mLock) { try { //Get HIDL service mProxy = IUsb.getService(); mProxy.linkToDeath(new DeathRecipient(pw), USB_HAL_DEATH_COOKIE); //Set callback, look back later mProxy.setCallback(mHALCallback); mProxy.queryPortStatus(); } catch (NoSuchElementException e) { ...... } } } 1 2 3 4 5 6 7 8 9 10 11 12
13
14
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();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 17
18
19
20 hardware\interfaces\usb\1.0\default\Usb.cpp uses EPOLL
, UEVENT mechanism, multi-channel IO blocking multiplexing
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); //create socket //payload is a conversion structure 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; //binding Event processing function uevent_event ev.data.ptr = (void *)uevent_event; epoll_fd = epoll_create(64); //Cycle wait for UEVENT event 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);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
hardware\interfaces\usb\1.0\default\Usb.cpp
Handle USB driver events from the kernel
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++);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
frameworks\base\services\usb\java\com\android\server\usb\UsbPortManager.java
Now let's take a look at the mHALCallback we just encountered
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;
}
......
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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;
}
}
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
frameworks\base\services\usb\java\com\android\server\usb\UsbPortManager.java
finally sent a broadcast to send out the port status information
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);
}
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
4. USB设备事务处理
frameworks\base\services\usb\java\com\android\server\usb\UsbDeviceManager.java
public UsbDeviceManager(Context context, UsbAlsaManager alsaManager,
UsbSettingsManager settingsManager) { //USB accessory mode check mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY); if (nativeIsStartRequested()) { if (DEBUG) S log.d(TAG, "accessory attached at boot"); startAccessoryMode(); } mHandler = new UsbHandler(FgThread.get().getLooper()); //Adb debugging is enabled by the developer boolean secureAdbEnabled = SystemProperties.getBoolean("ro.adb.secure", false ); boolean dataEncrypted = "1".equals(SystemProperties.get("vold.decrypt"));
if (secureAdbEnabled && !dataEncrypted) { mDebuggingManager = new UsbDebuggingManager(context); //usb debugging management } //corresponding to the broadcast sent above mContext.registerReceiver(mHostReceiver, new IntentFilter(UsbManager.ACTION_USB_PORT_CHANGED)); mContext.registerRecei ver(mChargingReceiver, new IntentFilter(Intent. ACTION_BATTERY_CHANGED)); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
frameworks\base\services\usb\java\com\android\server\usb\UsbDeviceManager.java
listens for message forwarding and processing transactions
//adb debug mode switch monitor
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();
}
}
};
//Receive USB status change
private final BroadcastReceiver mHostReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { UsbPort port = intent.getParcelableExtra(UsbManager.EXTRA_PORT); UsbPortStatus status = intent.get ParcelableExtra(UsbManager. EXTRA_PORT_STATUS); mHandler.updateHostState(port, status); //Pass it to the internal Handler for processing, no more in-depth} }; // Accept USB unplugging status 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);
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
Finally, UsbHandler handles affairs including MIDI, host/accessory mode, audio, adb debugging, status Notification, device increase and decrease status changes, etc. I won't go into details about it in detail, and I will analyze it later.
————————————————
Copyright statement: This article is an original article of CSDN blogger "SherlockCharlie", following the CC 4.0 BY-SA copyright agreement, please attach the original source link and this statement for reprinting .
Original link: https://blog.csdn.net/u013928208/article/details/84586238