Android usb 麥克風熱插拔

/* USB管理 */

frameworks/base/services/usb/java/com/android/server/usb/UsbSettingsManager.java

 

在 Android 系統中是用 廣播的方式來通知系統, USB 麥克風的熱插拔。

Linux 內核的設備熱插拔:

  • Linux 採用一種特殊類的的文件描述符套結字)專門用於Linux內核跟用戶空間之間的異步通信,這種技術通常被成爲NETLINK。

  • Uevent是一種在內核空間和用戶空間之間通信的機制,主要用於熱插拔事件(hotplug)

如 kobject 中檢測的設備的幾種狀態:

// include/linux/kobject.h
enum kobject_action 
{
    KOBJ_ADD,
    KOBJ_REMOVE,
    KOBJ_CHANGE,
    KOBJ_MOVE,
    KOBJ_ONLINE,
    KOBJ_OFFLINE,
    KOBJ_MAX
};

這些動作對應的事件相應有以下幾種:

// include/linux/kobject.h
static const char *kobject_actions[] = 
{
    [KOBJ_ADD]    = "add",
    [KOBJ_REMOVE] = "remove",
    [KOBJ_CHANGE] = "change",
    [KOBJ_MOVE]   = "move",
    [KOBJ_ONLINE] = "online",
};

linux 內核通過 add remove move 等動作來完成熱插拔動的檢測和事件上報。

Android 是 Linux 的事件機制上加入了 intent (廣播)。

 

 

下面來分析Android usb  麥克風熱插拔的 intent 廣播:

 

usb 麥克風插入/拔出的事件:

  • UsbManager.ACTION_USB_DEVICE_ATTACHED  - 插入廣播
  • UsbManager.ACTION_USB_DEVICE_DETACHED - 拔出廣播

在 APP 中檢查系統中的 UsbManager 的廣播來判斷 usb 麥克風是否插入或拔出。

 

usb麥克風插入,UsbManager調用:

從函數名上推測 deviceAttached 是檢測設備插入, deviceAttached 調用 createDeviceAttachedIntent , 發出usb設備插入的廣播 - UsbManager.ACTION_USB_DEVICE_ATTACHED 。

//  frameworks/base/services/usb/java/com/android/server/usb/UsbSettingsManager.java
public void deviceAttached(UsbDevice device)
{
    final Intent intent = createDeviceAttachedIntent(device);

    // Send broadcast to running activity with registered intent
    mUserContext.sendBroadcast(intent);

    if(MtpNotificationManager.shouldShowNotification(mPackageManager, device))
    {
        // Show notification if the device is MTP storage.
        mMtpNotificationManager.showNotification(device);
    }
    else
    {
        resolveActivity(intent, device);
    }
}

private static Intent createDeviceAttachedIntent(UsbDevice device)
{
    Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED);
    intent.putExtra(UsbManager.EXTRA_DEVICE, device);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    return intent;
}

 

同理usb麥克風拔出,UsbManager調用: deviceDetached 發出usb設備拔出的廣播 - UsbManager.ACTION_USB_DEVICE_DETACHED 。

//  frameworks/base/services/usb/java/com/android/server/usb/UsbSettingsManager.java
public void deviceDetached(UsbDevice device)
{
    // clear temporary permissions for the device
    mDevicePermissionMap.remove(device.getDeviceName());

    Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_DETACHED);
    intent.putExtra(UsbManager.EXTRA_DEVICE, device);
    if(DEBUG) Slog.d(TAG, "usbDeviceRemoved, sending " + intent);
    mContext.sendBroadcastAsUser(intent, UserHandle.ALL);

    mMtpNotificationManager.hideNotification(device.getDeviceId());
}

 

APP 中添加接收處理 usb 設備的類,打印 usb 麥克風插入/拔出狀態。

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.hardware.usb.UsbManager;
import android.util.Log;

/**
 * Created by huangsj on 2019/1/7.
 */

public class UsbReceiver extends BroadcastReceiver {
    private static final String TAG = "UsbReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "onReceive: "+intent.getAction());
        switch (intent.getAction()) {

            case UsbManager.ACTION_USB_DEVICE_DETACHED: {
                Log.d(TAG, "onReceive: ACTION_USB_DEVICE_DETACHED");
                break;
            }
            case UsbManager.ACTION_USB_DEVICE_ATTACHED: {
                Log.d(TAG, "onReceive: ACTION_USB_DEVICE_ATTACHED");
                break;
            }
            default:
                break;
        }
    }
}

通過 intent.getAction()  接收廣播,並判斷是否是 usb 麥克風的廣播。

 

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