Android8.0 USB系统框架
USB(通用串行總線)主機模式向外設(shè)進(jìn)行供電,使 Android 設(shè)備能夠驅(qū)動 USB 總線,并且可以使用各種 USB 外設(shè)(包括音頻接口,存儲,MIDI),USB 和藍(lán)牙低功耗連接都可以用于傳輸 MIDI 協(xié)議。USB配件模式,受外設(shè)供電驅(qū)動,包括數(shù)據(jù)傳輸,充電。USB開發(fā)模式,應(yīng)用調(diào)試,唯一可見的外設(shè)功能是 Android fastboot 或 Android 調(diào)試橋 (adb)。fastboot 和 adb 協(xié)議所在層高于 USB 批量數(shù)據(jù)傳輸模式所在層。
Android 平臺支持使用即插即用的 USB 攝像頭(例如網(wǎng)絡(luò)攝像頭),但前提是這些攝像頭采用標(biāo)準(zhǔn)的 Android Camera2 API 和攝像頭 HIDL 接口,全新的 USB 攝像頭 HAL 進(jìn)程是外接攝像頭提供程序的一部分,該提供程序會監(jiān)聽 USB 設(shè)備可用性,并相應(yīng)地枚舉外接攝像頭設(shè)備。該進(jìn)程具有與內(nèi)置攝像頭 HAL 進(jìn)程類似的權(quán)限和 SE 策略。直接與 USB 設(shè)備通信的第三方網(wǎng)絡(luò)攝像頭應(yīng)用訪問 UVC 設(shè)備時所需的攝像頭權(quán)限與所有常規(guī)攝像頭應(yīng)用所需的權(quán)限相同。
1. Usb服務(wù)啟動
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服務(wù)初始化@Overridepublic void onBootPhase(int phase) {if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {mUsbService.systemReady(); //系統(tǒng)準(zhǔn)備就緒} else if (phase == SystemService.PHASE_BOOT_COMPLETED) {mUsbService.bootCompleted();//系統(tǒng)啟動完成}}......}frameworks\base\services\usb\java\com\android\server\usb\UsbService.java
初始化USB服務(wù)
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設(shè)備打開
frameworks\base\core\java\android\hardware\usb\UsbManager.java
public UsbDeviceConnection openDevice(UsbDevice device) {try {String deviceName = device.getDeviceName();//打開USB設(shè)備,返回文件描述符FDParcelFileDescriptor pfd = mService.openDevice(deviceName);if (pfd != null) {//創(chuàng)建Socket連接通道,用于數(shù)據(jù)指令傳輸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設(shè)備列表中查找一個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);//調(diào)用系統(tǒng)提供的USB設(shè)備打開函數(shù)struct usb_device* device = usb_device_open(deviceNameStr);env->ReleaseStringUTFChars(deviceName, deviceNameStr);//獲得USB設(shè)備的文件描述符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); //打開設(shè)備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設(shè)備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)); //分配內(nèi)存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)); //讀取設(shè)備描述符長度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
調(diào)用JNI層打開指定的USB設(shè)備
3.USB設(shè)備檢測
frameworks\base\services\usb\java\com\android\server\usb\UsbPortManager.java
設(shè)備端口管理
frameworks\base\services\usb\java\com\android\server\usb\UsbPortManager.java
private void connectToProxy(IndentingPrintWriter pw) {synchronized (mLock) {try {//獲取HIDL服務(wù)mProxy = IUsb.getService(); mProxy.linkToDeath(new DeathRecipient(pw), USB_HAL_DEATH_COOKIE);//設(shè)置回調(diào),一會兒再回頭看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);//創(chuàng)建線程,運行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阻塞復(fù)用
hardware\interfaces\usb\1.0\default\Usb.cpp
處理來自內(nèi)核的USB驅(qū)動事件
frameworks\base\services\usb\java\com\android\server\usb\UsbPortManager.java
現(xiàn)在我們來看看剛剛的遇到的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設(shè)備的插入刪除移除// 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
終于發(fā)送了一個廣播將端口狀態(tài)信息發(fā)送出去
4. USB設(shè)備事務(wù)處理
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());//開發(fā)人員adb調(diào)試是否打開boolean secureAdbEnabled = SystemProperties.getBoolean("ro.adb.secure", false);boolean dataEncrypted = "1".equals(SystemProperties.get("vold.decrypt"));if (secureAdbEnabled && !dataEncrypted) {mDebuggingManager = new UsbDebuggingManager(context); //usb調(diào)試管理}//對應(yīng)上面發(fā)送的廣播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
監(jiān)聽消息轉(zhuǎn)發(fā)處理事務(wù)
最后在UsbHandler里處理包括MIDI,主機/配件模式,音頻,adb調(diào)試,狀態(tài)Notification,設(shè)備的增減狀態(tài)變化等事務(wù)。具體就不再細(xì)究了,以后遇到再分析。
總結(jié)
以上是生活随笔為你收集整理的Android8.0 USB系统框架的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: matlab搭建多径模型,基于MATLA
- 下一篇: 信息安全密码学:DES算法的核心 E盒、