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;
        ......
        @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();//系統啓動完成
            }
        }
        ......
    }
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
初始化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);
    }
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

 //系統音頻服務
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;
    }
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設備打開
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;
    }
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");
            }
            //從已存在的USB設備列表中查找一個
            UsbDevice 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);
    //調用系統提供的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);
}
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設備檢測
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);
    }
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 {
                //獲取HIDL服務
                mProxy = IUsb.getService(); 
                mProxy.linkToDeath(new DeathRecipient(pw), USB_HAL_DEATH_COOKIE);
                //設置回調,一會兒再回頭看
                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
使用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);
        }
    }
}
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
處理來自內核的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++);
    }
}
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
現在我們來看看剛剛的遇到的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;
        }
        ......
    };
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
終於發送了一個廣播將端口狀態信息發送出去

 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配件模式檢查
        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));
    }
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
監聽消息轉發處理事務

 //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);
        }
    };
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
最後在UsbHandler裏處理包括MIDI,主機/配件模式,音頻,adb調試,狀態Notification,設備的增減狀態變化等事務。具體就不再細究了,以後遇到再分析。


————————————————
版權聲明:本文爲CSDN博主「SherlockCharlie」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/u013928208/article/details/84586238

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章