Android8.0 USB系统框架
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 設備時所需的攝像頭權限與所有常規攝像頭應用所需的權限相同。
1. Usb服務啟動
frameworks\base\services\usb\java\com\android\server\usb\UsbService.java
public static class Lifecycle extends SystemService {private UsbService mUsbService;......@Overridepublic void onStart() { mUsbService = new UsbService(getContext());} //USB服務初始化@Overridepublic 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服務
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
2. USB設備打開
frameworks\base\core\java\android\hardware\usb\UsbManager.java
public UsbDeviceConnection openDevice(UsbDevice device) {try {String deviceName = device.getDeviceName();//打開USB設備,返回文件描述符FDParcelFileDescriptor 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) */@Overridepublic ParcelFileDescriptor openDevice(String deviceName) {ParcelFileDescriptor fd = null;if (mHostManager != null) {synchronized (mLock) {if (deviceName != null) {int userIdInt = UserHandle.getCallingUserId();boolean isCurrentUser = isCallerInCurrentUserProfileGroupLocked();//以主機模式打開制定USBif (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 fdsdevice->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設備
3.USB設備檢測
frameworks\base\services\usb\java\com\android\server\usb\UsbPortManager.java
設備端口管理
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);//創建線程,運行workif (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阻塞復用
hardware\interfaces\usb\1.0\default\Usb.cpp
處理來自內核的USB驅動事件
frameworks\base\services\usb\java\com\android\server\usb\UsbPortManager.java
現在我們來看看剛剛的遇到的mHALCallback
frameworks\base\services\usb\java\com\android\server\usb\UsbPortManager.java
private final Handler mHandler = new Handler(FgThread.get().getLooper()) {@Overridepublic 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 earlyhandlePortRemovedLocked(portInfo, pw);break;}}}frameworks\base\services\usb\java\com\android\server\usb\UsbPortManager.java
終于發送了一個廣播將端口狀態信息發送出去
4. USB設備事務處理
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
監聽消息轉發處理事務
最后在UsbHandler里處理包括MIDI,主機/配件模式,音頻,adb調試,狀態Notification,設備的增減狀態變化等事務。具體就不再細究了,以后遇到再分析。
總結
以上是生活随笔為你收集整理的Android8.0 USB系统框架的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: matlab搭建多径模型,基于MATLA
- 下一篇: Android Fragment重叠问题