USBDeviceManager是一个Android系统中用于管理USB设备的类,它是系统服务之一。其主要功能是控制USB设备的连接和断开,以及管理USB设备的权限和状态。下面是对USBDeviceManager代码的简要分析:
USBDeviceManager的构造函数:
在USBDeviceManager的构造函数中,它会调用系统服务框架的registerService方法,将自己注册为系统服务。在注册完成后,会创建一个名为"usb"的UEventObserver对象,并通过该对象注册监听USB设备插入和拔出事件的广播接收器。同时,它还会创建一个名为"android.hardware.usb.UsbDeviceManager.action.USB_STATE"的IntentFilter对象,并通过该对象注册监听USB设备状态变化的广播接收器。
onReceive方法:
当收到广播事件时,会调用onReceive方法来处理事件。在该方法中,它会获取广播中包含的设备状态信息,并根据状态信息来执行不同的操作,例如检查权限、发送USB设备插入/拔出的广播、更新USB设备的状态等。
getDeviceList方法:
该方法用于获取当前已连接的USB设备列表。它会调用系统服务的getUsbManager方法来获取UsbManager对象,然后调用UsbManager对象的getDeviceList方法来获取设备列表。
setDevicePackage方法:
该方法用于设置USB设备的包名。它会检查包名是否存在,并将包名保存到SharedPreferences中。
setCurrentUser方法:USBDeviceManager是一个Android系统中用于管理USB设备的类,它是系统服务之一。其主要功能是控制USB设备的连接和断开,以及管理USB设备的权限和状态。下面是对USBDeviceManager代码的简要分析:
USBDeviceManager的构造函数:
在USBDeviceManager的构造函数中,它会调用系统服务框架的registerService方法,将自己注册为系统服务。在注册完成后,会创建一个名为"usb"的UEventObserver对象,并通过该对象注册监听USB设备插入和拔出事件的广播接收器。同时,它还会创建一个名为"android.hardware.usb.UsbDeviceManager.action.USB_STATE"的IntentFilter对象,并通过该对象注册监听USB设备状态变化的广播接收器。
onReceive方法:
当收到广播事件时,会调用onReceive方法来处理事件。在该方法中,它会获取广播中包含的设备状态信息,并根据状态信息来执行不同的操作,例如检查权限、发送USB设备插入/拔出的广播、更新USB设备的状态等。
getDeviceList方法:
该方法用于获取当前已连接的USB设备列表。它会调用系统服务的getUsbManager方法来获取UsbManager对象,然后调用UsbManager对象的getDeviceList方法来获取设备列表。
setDevicePackage方法:
该方法用于设置USB设备的包名。它会检查包名是否存在,并将包名保存到SharedPreferences中。
setCurrentUser方法:
该方法用于设置当前用户。它会将当前用户ID保存到SharedPreferences中。
setPermission方法:
该方法用于设置USB设备的权限。它会检查当前应用程序是否具有权限,如果没有,则向用户发出请求。如果用户同意,则调用UsbManager对象的grantPermission方法授予权限。
总的来说,USBDeviceManager类是Android系统中用于管理USB设备的重要类之一。通过它可以实现USB设备的连接和断开、权限的控制、状态的管理等功能,为上层应用提供方便的USB设备管理接口。
UsbDeviceManager的构造函数
public UsbDeviceManager(Context context, UsbAlsaManager alsaManager,
UsbSettingsManager settingsManager, UsbPermissionManager permissionManager) {
mContext = context;
mContentResolver = context.getContentResolver();
PackageManager pm = mContext.getPackageManager();
mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
initRndisAddress();
int operationId = sUsbOperationCount.incrementAndGet();
boolean halNotPresent = false;
mUsbGadgetHal = UsbGadgetHalInstance.getInstance(this, null);
Slog.d(TAG, "getInstance done");
mControlFds = new HashMap<>();
FileDescriptor mtpFd = nativeOpenControl(UsbManager.USB_FUNCTION_MTP);
if (mtpFd == null) {
Slog.e(TAG, "Failed to open control for mtp");
}
mControlFds.put(UsbManager.FUNCTION_MTP, mtpFd);
FileDescriptor ptpFd = nativeOpenControl(UsbManager.USB_FUNCTION_PTP);
if (ptpFd == null) {
Slog.e(TAG, "Failed to open control for ptp");
}
mControlFds.put(UsbManager.FUNCTION_PTP, ptpFd);
if (mUsbGadgetHal == null) {
/**
* Initialze the legacy UsbHandler
*/
mHandler = new UsbHandlerLegacy(FgThread.get().getLooper(), mContext, this,
alsaManager, permissionManager);
} else {
/**
* Initialize HAL based UsbHandler
*/
mHandler = new UsbHandlerHal(FgThread.get().getLooper(), mContext, this,
alsaManager, permissionManager);
}
mHandler.handlerInitDone(operationId);
if (nativeIsStartRequested()) {
if (DEBUG) Slog.d(TAG, "accessory attached at boot");
startAccessoryMode();
}
BroadcastReceiver portReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
ParcelableUsbPort port = intent.getParcelableExtra(UsbManager.EXTRA_PORT, android.hardware.usb.ParcelableUsbPort.class);
UsbPortStatus status = intent.getParcelableExtra(UsbManager.EXTRA_PORT_STATUS, android.hardware.usb.UsbPortStatus.class);
mHandler.updateHostState(
port.getUsbPort(context.getSystemService(UsbManager.class)), status);
}
};
BroadcastReceiver chargingReceiver = 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);
}
};
BroadcastReceiver hostReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Iterator devices = ((UsbManager) context.getSystemService(Context.USB_SERVICE))
.getDeviceList().entrySet().iterator();
if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
mHandler.sendMessage(MSG_UPDATE_HOST_STATE, devices, true);
} else {
mHandler.sendMessage(MSG_UPDATE_HOST_STATE, devices, false);
}
}
};
BroadcastReceiver languageChangedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
mHandler.sendEmptyMessage(MSG_LOCALE_CHANGED);
}
};
mContext.registerReceiver(portReceiver,
new IntentFilter(UsbManager.ACTION_USB_PORT_CHANGED));
mContext.registerReceiver(chargingReceiver,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
IntentFilter filter =
new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
mContext.registerReceiver(hostReceiver, filter);
mContext.registerReceiver(languageChangedReceiver,
new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
// Watch for USB configuration changes
mUEventObserver = new UsbUEventObserver();
mUEventObserver.startObserving(USB_STATE_MATCH);
mUEventObserver.startObserving(ACCESSORY_START_MATCH);
sEventLogger = new EventLogger(DUMPSYS_LOG_BUFFER, "UsbDeviceManager activity");
}
这段代码是 Android 系统中的 UsbDeviceManager
类的构造函数,用于初始化和管理 Android 设备作为 USB 设备时的各种功能和状态。这是一个核心部分,负责处理 USB 相关的任务。让我们分段分析这段代码:
1. Context 和初始化
mContext = context;
mContentResolver = context.getContentResolver();
PackageManager pm = mContext.getPackageManager();
mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
initRndisAddress();
- 这些行代码保存了
Context
和ContentResolver
,并检查设备是否支持 USB 附件(Accessory)功能,同时调用initRndisAddress()
来初始化 RNDIS(Remote Network Driver Interface Specification)地址。
2. USB Gadget HAL 实例化
int operationId = sUsbOperationCount.incrementAndGet();
boolean halNotPresent = false;
mUsbGadgetHal = UsbGadgetHalInstance.getInstance(this, null);
Slog.d(TAG, "getInstance done");
- 这段代码递增了 USB 操作计数器,并尝试获取
UsbGadgetHalInstance
的实例。UsbGadgetHal
是用于管理 USB Gadget(设备端)的 HAL(Hardware Abstraction Layer)。获取实例后会输出一条日志。
3. 文件描述符初始化
mControlFds = new HashMap<>();
FileDescriptor mtpFd = nativeOpenControl(UsbManager.USB_FUNCTION_MTP);
if (mtpFd == null) {
Slog.e(TAG, "Failed to open control for mtp");
}
mControlFds.put(UsbManager.FUNCTION_MTP, mtpFd);
FileDescriptor ptpFd = nativeOpenControl(UsbManager.USB_FUNCTION_PTP);
if (ptpFd == null) {
Slog.e(TAG, "Failed to open control for ptp");
}
mControlFds.put(UsbManager.FUNCTION_PTP, ptpFd);
- 这部分代码通过本地方法
nativeOpenControl()
打开控制 USB 功能的文件描述符(MTP 和 PTP),并将它们存储在mControlFds
HashMap 中。如果无法打开文件描述符,系统会记录错误日志。
4. USB Handler 初始化
if (mUsbGadgetHal == null) {
/**
* Initialze the legacy UsbHandler
*/
mHandler = new UsbHandlerLegacy(FgThread.get().getLooper(), mContext, this,
alsaManager, permissionManager);
} else {
/**
* Initialize HAL based UsbHandler
*/
mHandler = new UsbHandlerHal(FgThread.get().getLooper(), mContext, this,
alsaManager, permissionManager);
}
mHandler.handlerInitDone(operationId);
- 根据
UsbGadgetHal
是否可用,初始化适当的 USB Handler。UsbHandlerLegacy
用于不支持 HAL 的情况,UsbHandlerHal
用于支持 HAL 的情况。初始化完成后,调用handlerInitDone()
方法。
5. 处理启动时的配件模式
if (nativeIsStartRequested()) {
if (DEBUG) Slog.d(TAG, "accessory attached at boot");
startAccessoryMode();
}
- 检查是否请求启动,如果在启动时连接了 USB 配件(Accessory),系统会启动配件模式。
6. 注册系统广播接收器
BroadcastReceiver portReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
ParcelableUsbPort port = intent.getParcelableExtra(UsbManager.EXTRA_PORT, android.hardware.usb.ParcelableUsbPort.class);
UsbPortStatus status = intent.getParcelableExtra(UsbManager.EXTRA_PORT_STATUS, android.hardware.usb.UsbPortStatus.class);
mHandler.updateHostState(
port.getUsbPort(context.getSystemService(UsbManager.class)), status);
}
};
BroadcastReceiver chargingReceiver = 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);
}
};
BroadcastReceiver hostReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Iterator devices = ((UsbManager) context.getSystemService(Context.USB_SERVICE))
.getDeviceList().entrySet().iterator();
if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
mHandler.sendMessage(MSG_UPDATE_HOST_STATE, devices, true);
} else {
mHandler.sendMessage(MSG_UPDATE_HOST_STATE, devices, false);
}
}
};
BroadcastReceiver languageChangedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
mHandler.sendEmptyMessage(MSG_LOCALE_CHANGED);
}
};
mContext.registerReceiver(portReceiver,
new IntentFilter(UsbManager.ACTION_USB_PORT_CHANGED));
mContext.registerReceiver(chargingReceiver,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
IntentFilter filter =
new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
mContext.registerReceiver(hostReceiver, filter);
mContext.registerReceiver(languageChangedReceiver,
new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
- 注册了多个广播接收器:
- portReceiver: 监听 USB 端口状态变化(
UsbManager.ACTION_USB_PORT_CHANGED
)。 - chargingReceiver: 监听充电状态变化(
Intent.ACTION_BATTERY_CHANGED
)。 - hostReceiver: 监听 USB 设备连接和断开(
UsbManager.ACTION_USB_DEVICE_ATTACHED
和UsbManager.ACTION_USB_DEVICE_DETACHED
)。 - languageChangedReceiver: 监听系统语言变化(
Intent.ACTION_LOCALE_CHANGED
)。
- portReceiver: 监听 USB 端口状态变化(
7. 启动 UEvent 观察者
mUEventObserver = new UsbUEventObserver();
mUEventObserver.startObserving(USB_STATE_MATCH);
mUEventObserver.startObserving(ACCESSORY_START_MATCH);
sEventLogger = new EventLogger(DUMPSYS_LOG_BUFFER, "UsbDeviceManager activity");
-
创建并启动了
UsbUEventObserver
,用于监听内核事件(UEvent),这些事件通常与 USB 状态变化有关。USB_STATE_MATCH
和ACCESSORY_START_MATCH
是要观察的事件模式。 -
最后,初始化了一个事件日志记录器
sEventLogger
,用于记录 USB 设备管理器的活动。
该方法用于设置当前用户。它会将当前用户ID保存到SharedPreferences中。
setPermission方法:
该方法用于设置USB设备的权限。它会检查当前应用程序是否具有权限,如果没有,则向用户发出请求。如果用户同意,则调用UsbManager对象的grantPermission方法授予权限。
总的来说,USBDeviceManager类是Android系统中用于管理USB设备的重要类之一。通过它可以实现USB设备的连接和断开、权限的控制、状态的管理等功能,为上层应用提供方便的USB设备管理接口。
UsbDeviceManager 中 UsbHandlerLegacy 对象
在 UsbDeviceManager
中,UsbHandlerLegacy
对象是一个处理 USB 相关事件的类。它主要负责处理 USB 设备的连接、断开、数据传输等操作。
private static final class UsbHandlerLegacy extends UsbHandler {
/**
* The non-persistent property which stores the current USB settings.
*/
private static final String USB_CONFIG_PROPERTY = "sys.usb.config";
/**
* The non-persistent property which stores the current USB actual state.
*/
private static final String USB_STATE_PROPERTY = "sys.usb.state";
private HashMap<String, HashMap<String, Pair<String, String>>> mOemModeMap;
private String mCurrentOemFunctions;
private String mCurrentFunctionsStr;
private boolean mUsbDataUnlocked;
/**
* Keeps track of the latest setCurrentUsbFunctions request number.
*/
private int mCurrentRequest = 0;
UsbHandlerLegacy(Looper looper, Context context, UsbDeviceManager deviceManager,
UsbAlsaManager alsaManager, UsbPermissionManager permissionManager) {
super(looper, context, deviceManager, alsaManager, permissionManager);
try {
readOemUsbOverrideConfig(context);
// Restore default functions.
mCurrentOemFunctions = getSystemProperty(getPersistProp(false),
UsbManager.USB_FUNCTION_NONE);
if (isNormalBoot()) {
mCurrentFunctionsStr = getSystemProperty(USB_CONFIG_PROPERTY,
UsbManager.USB_FUNCTION_NONE);
mCurrentFunctionsApplied = mCurrentFunctionsStr.equals(
getSystemProperty(USB_STATE_PROPERTY, UsbManager.USB_FUNCTION_NONE));
} else {
mCurrentFunctionsStr = getSystemProperty(getPersistProp(true),
UsbManager.USB_FUNCTION_NONE);
mCurrentFunctionsApplied = getSystemProperty(USB_CONFIG_PROPERTY,
UsbManager.USB_FUNCTION_NONE).equals(
getSystemProperty(USB_STATE_PROPERTY, UsbManager.USB_FUNCTION_NONE));
}
mCurrentFunctions = UsbManager.FUNCTION_NONE;
mCurrentUsbFunctionsReceived = true;
mUsbSpeed = UsbSpeed.UNKNOWN;
mCurrentGadgetHalVersion = UsbManager.GADGET_HAL_NOT_SUPPORTED;
String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
updateState(state);
} catch (Exception e) {
Slog.e(TAG, "Error initializing UsbHandler", e);
}
}
@Override
public void handlerInitDone(int operationId) {
}
private void readOemUsbOverrideConfig(Context context) {
String[] configList = context.getResources().getStringArray(
com.android.internal.R.array.config_oemUsbModeOverride);
if (configList != null) {
for (String config : configList) {
String[] items = config.split(":");
if (items.length == 3 || items.length == 4) {
if (mOemModeMap == null) {
mOemModeMap = new HashMap<>();
}
HashMap<String, Pair<String, String>> overrideMap =
mOemModeMap.get(items[0]);
if (overrideMap == null) {
overrideMap = new HashMap<>();
mOemModeMap.put(items[0], overrideMap);
}
// Favoring the first combination if duplicate exists
if (!overrideMap.containsKey(items[1])) {
if (items.length == 3) {
overrideMap.put(items[1], new Pair<>(items[2], ""));
} else {
overrideMap.put(items[1], new Pair<>(items[2], items[3]));
}
}
}
}
}
}
private String applyOemOverrideFunction(String usbFunctions) {
if ((usbFunctions == null) || (mOemModeMap == null)) {
return usbFunctions;
}
String bootMode = getSystemProperty(BOOT_MODE_PROPERTY, "unknown");
Slog.d(TAG, "applyOemOverride usbfunctions=" + usbFunctions + " bootmode=" + bootMode);
Map<String, Pair<String, String>> overridesMap =
mOemModeMap.get(bootMode);
// Check to ensure that the oem is not overriding in the normal
// boot mode
if (overridesMap != null && !(bootMode.equals(NORMAL_BOOT)
|| bootMode.equals("unknown"))) {
Pair<String, String> overrideFunctions =
overridesMap.get(usbFunctions);
if (overrideFunctions != null) {
Slog.d(TAG, "OEM USB override: " + usbFunctions
+ " ==> " + overrideFunctions.first
+ " persist across reboot "
+ overrideFunctions.second);
if (!overrideFunctions.second.equals("")) {
String newFunction;
if (isAdbEnabled()) {
newFunction = addFunction(overrideFunctions.second,
UsbManager.USB_FUNCTION_ADB);
} else {
newFunction = overrideFunctions.second;
}
Slog.d(TAG, "OEM USB override persisting: " + newFunction + "in prop: "
+ getPersistProp(false));
setSystemProperty(getPersistProp(false), newFunction);
}
return overrideFunctions.first;
} else if (isAdbEnabled()) {
String newFunction = addFunction(UsbManager.USB_FUNCTION_NONE,
UsbManager.USB_FUNCTION_ADB);
setSystemProperty(getPersistProp(false), newFunction);
} else {
setSystemProperty(getPersistProp(false), UsbManager.USB_FUNCTION_NONE);
}
}
// return passed in functions as is.
return usbFunctions;
}
private boolean waitForState(String state) {
// wait for the transition to complete.
// give up after 1 second.
String value = null;
for (int i = 0; i < 20; i++) {
// State transition is done when sys.usb.state is set to the new configuration
value = getSystemProperty(USB_STATE_PROPERTY, "");
if (state.equals(value)) return true;
SystemClock.sleep(50);
}
Slog.e(TAG, "waitForState(" + state + ") FAILED: got " + value);
return false;
}
private void setUsbConfig(String config) {
if (DEBUG) Slog.d(TAG, "setUsbConfig(" + config + ")");
/**
* set the new configuration
* we always set it due to b/23631400, where adbd was getting killed
* and not restarted due to property timeouts on some devices
*/
setSystemProperty(USB_CONFIG_PROPERTY, config);
}
@Override
protected void setEnabledFunctions(long usbFunctions,
boolean forceRestart, int operationId) {
boolean usbDataUnlocked = isUsbDataTransferActive(usbFunctions);
if (DEBUG) {
Slog.d(TAG, "setEnabledFunctions functions=" + usbFunctions +
" ,forceRestart=" + forceRestart +
" ,usbDataUnlocked=" + usbDataUnlocked +
" ,operationId=" + operationId);
}
if (usbDataUnlocked != mUsbDataUnlocked) {
mUsbDataUnlocked = usbDataUnlocked;
updateUsbNotification(false);
forceRestart = true;
}
/**
* Try to set the enabled functions.
*/
final long oldFunctions = mCurrentFunctions;
final boolean oldFunctionsApplied = mCurrentFunctionsApplied;
if (trySetEnabledFunctions(usbFunctions, forceRestart)) {
return;
}
/**
* Didn't work. Try to revert changes.
* We always reapply the policy in case certain constraints changed such as
* user restrictions independently of any other new functions we were
* trying to activate.
*/
if (oldFunctionsApplied && oldFunctions != usbFunctions) {
Slog.e(TAG, "Failsafe 1: Restoring previous USB functions.");
if (trySetEnabledFunctions(oldFunctions, false)) {
return;
}
}
/**
* Still didn't work. Try to restore the default functions.
*/
Slog.e(TAG, "Failsafe 2: Restoring default USB functions.");
if (trySetEnabledFunctions(UsbManager.FUNCTION_NONE, false)) {
return;
}
/**
* Now we're desperate. Ignore the default functions.
* Try to get ADB working if enabled.
*/
Slog.e(TAG, "Failsafe 3: Restoring empty function list (with ADB if enabled).");
if (trySetEnabledFunctions(UsbManager.FUNCTION_NONE, false)) {
return;
}
/**
* Ouch.
*/
Slog.e(TAG, "Unable to set any USB functions!");
}
private boolean isNormalBoot() {
String bootMode = getSystemProperty(BOOT_MODE_PROPERTY, "unknown");
return bootMode.equals(NORMAL_BOOT) || bootMode.equals("unknown");
}
protected String applyAdbFunction(String functions) {
// Do not pass null pointer to the UsbManager.
// There isn't a check there.
if (functions == null) {
functions = "";
}
if (isAdbEnabled()) {
functions = addFunction(functions, UsbManager.USB_FUNCTION_ADB);
} else {
functions = removeFunction(functions, UsbManager.USB_FUNCTION_ADB);
}
return functions;
}
private boolean trySetEnabledFunctions(long usbFunctions, boolean forceRestart) {
String functions = null;
if (usbFunctions != UsbManager.FUNCTION_NONE) {
functions = UsbManager.usbFunctionsToString(usbFunctions);
}
mCurrentFunctions = usbFunctions;
if (functions == null || applyAdbFunction(functions)
.equals(UsbManager.USB_FUNCTION_NONE)) {
functions = UsbManager.usbFunctionsToString(getChargingFunctions());
}
functions = applyAdbFunction(functions);
String oemFunctions = applyOemOverrideFunction(functions);
if (!isNormalBoot() && !mCurrentFunctionsStr.equals(functions)) {
setSystemProperty(getPersistProp(true), functions);
}
if ((!functions.equals(oemFunctions)
&& !mCurrentOemFunctions.equals(oemFunctions))
|| !mCurrentFunctionsStr.equals(functions)
|| !mCurrentFunctionsApplied
|| forceRestart) {
mCurrentFunctionsStr = functions;
mCurrentOemFunctions = oemFunctions;
mCurrentFunctionsApplied = false;
/**
* Kick the USB stack to close existing connections.
*/
setUsbConfig(UsbManager.USB_FUNCTION_NONE);
if (!waitForState(UsbManager.USB_FUNCTION_NONE)) {
Slog.e(TAG, "Failed to kick USB config");
return false;
}
/**
* Set the new USB configuration.
*/
setUsbConfig(oemFunctions);
if (mBootCompleted
&& (containsFunction(functions, UsbManager.USB_FUNCTION_MTP)
|| containsFunction(functions, UsbManager.USB_FUNCTION_PTP))) {
/**
* Start up dependent services.
*/
updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions));
}
if (!waitForState(oemFunctions)) {
Slog.e(TAG, "Failed to switch USB config to " + functions);
return false;
}
mCurrentFunctionsApplied = true;
}
return true;
}
private String getPersistProp(boolean functions) {
String bootMode = getSystemProperty(BOOT_MODE_PROPERTY, "unknown");
String persistProp = USB_PERSISTENT_CONFIG_PROPERTY;
if (!(bootMode.equals(NORMAL_BOOT) || bootMode.equals("unknown"))) {
if (functions) {
persistProp = "persist.sys.usb." + bootMode + ".func";
} else {
persistProp = "persist.sys.usb." + bootMode + ".config";
}
}
return persistProp;
}
private static String addFunction(String functions, String function) {
if (UsbManager.USB_FUNCTION_NONE.equals(functions)) {
return function;
}
if (!containsFunction(functions, function)) {
if (functions.length() > 0) {
functions += ",";
}
functions += function;
}
return functions;
}
private static String removeFunction(String functions, String function) {
String[] split = functions.split(",");
for (int i = 0; i < split.length; i++) {
if (function.equals(split[i])) {
split[i] = null;
}
}
if (split.length == 1 && split[0] == null) {
return UsbManager.USB_FUNCTION_NONE;
}
StringBuilder builder = new StringBuilder();
for (int i = 0; i < split.length; i++) {
String s = split[i];
if (s != null) {
if (builder.length() > 0) {
builder.append(",");
}
builder.append(s);
}
}
return builder.toString();
}
static boolean containsFunction(String functions, String function) {
int index = functions.indexOf(function);
if (index < 0) return false;
if (index > 0 && functions.charAt(index - 1) != ',') return false;
int charAfter = index + function.length();
if (charAfter < functions.length() && functions.charAt(charAfter) != ',') return false;
return true;
}
/**
* This callback function is only applicable for USB Gadget HAL,
* USBHandlerLegacy does not supported it.
*/
@Override
public void setCurrentUsbFunctionsCb(long functions,
int status, int mRequest, long mFunctions, boolean mChargingFunctions){
}
/**
* This callback function is only applicable for USB Gadget HAL,
* USBHandlerLegacy does not supported it.
*/
@Override
public void getUsbSpeedCb(int speed){
}
/**
* This callback function is only applicable for USB Gadget HAL,
* USBHandlerLegacy does not supported it.
*/
@Override
public void resetCb(int status){
}
}
这段代码定义了一个名为 UsbHandlerLegacy
的类,该类继承自 UsbHandler
,用于处理 Android 系统中的 USB 配置和管理。以下是代码的主要功能和流程的简要说明:
构造函数 UsbHandlerLegacy
:
- 初始化方法,负责读取 OEM USB 覆盖配置 (
readOemUsbOverrideConfig
),恢复默认功能,并更新 USB 状态。 - 根据设备的启动模式(普通启动或其他模式)来获取并设置当前 USB 的功能状态。
核心方法:
-
readOemUsbOverrideConfig
:- 读取 OEM 的 USB 模式覆盖配置,存储到
mOemModeMap
中。该配置可能包含与不同启动模式相关的 USB 功能。
- 读取 OEM 的 USB 模式覆盖配置,存储到
-
applyOemOverrideFunction
:- 根据当前启动模式和 USB 功能,应用 OEM 的覆盖功能,调整系统的 USB 设置。
-
waitForState
:- 等待 USB 状态的转换完成,通过检查
USB_STATE_PROPERTY
的值来确认是否完成。
- 等待 USB 状态的转换完成,通过检查
-
setUsbConfig
:- 设置新的 USB 配置,通常通过更改
USB_CONFIG_PROPERTY
的值来实现。
- 设置新的 USB 配置,通常通过更改
-
setEnabledFunctions
:- 启用指定的 USB 功能,并在必要时强制重新启动 USB 子系统。如果设置失败,则尝试恢复到先前的功能或默认功能。
-
trySetEnabledFunctions
:- 尝试设置启用的 USB 功能,应用 ADB 和 OEM 的覆盖配置,更新系统属性,并通过调用
waitForState
确认配置是否生效。
- 尝试设置启用的 USB 功能,应用 ADB 和 OEM 的覆盖配置,更新系统属性,并通过调用
-
applyAdbFunction
:- 根据当前 ADB(Android 调试桥)的状态,添加或移除 USB 功能字符串中的 ADB 功能。
-
getPersistProp
:- 根据设备的启动模式,返回适当的持久化属性名称。
回调方法:
setCurrentUsbFunctionsCb
,getUsbSpeedCb
,resetCb
:这些方法在 USB Gadget HAL(硬件抽象层)中是适用的,但在UsbHandlerLegacy
中没有实现。
整体流程:
UsbHandlerLegacy的构造函数大致分为三步。首先看第一步,读取oem厂商的关于usb功能的覆盖配置。
private void readOemUsbOverrideConfig(Context context) {
// 数组每一项的格式为[bootmode]:[original USB mode]:[USB mode used]
String[] configList = context.getResources().getStringArray(
com.android.internal.R.array.config_oemUsbModeOverride);
if (configList != null) {
for (String config : configList) {
String[] items = config.split(":");
if (items.length == 3 || items.length == 4) {
if (mOemModeMap == null) {
mOemModeMap = new HashMap<>();
}
HashMap<String, Pair<String, String>> overrideMap =
mOemModeMap.get(items[0]);
if (overrideMap == null) {
overrideMap = new HashMap<>();
mOemModeMap.put(items[0], overrideMap);
}
// Favoring the first combination if duplicate exists
if (!overrideMap.containsKey(items[1])) {
if (items.length == 3) {
overrideMap.put(items[1], new Pair<>(items[2], ""));
} else {
overrideMap.put(items[1], new Pair<>(items[2], items[3]));
}
}
}
}
}
}
读取的是config_oemUsbModeOverride
数组,然后保存到mOemModeMap中。数组每一项的格式为[bootmode]:[original USB mode]:[USB mode used]
,保存的格式可以大致描述为HashMap<bootmode, HashMap<original_usb_mode, Pair<usb_mode_used, "">
。我的项目中,这个数组为空。
然后第二步,读取了各种属性值(只考虑正常启动模式),如下。
- mCurrentOemFunctions的值是
persist.sys.usb.config
属性的值。按照源码注释,这个属性值存储了adb的开启状态(如果开启了adb,那么这个值会包含adb字符串)。另外,源码注释说这个属性也可以运营商定制的一些功能,但是只用于测试目的。 - mCurrentFunctionsStr的值是
sys.usb.config
属性值。这个属性表示当前设置的usb功能的值。在日常工作中,我们可以通过adb shell命令设置这个属性值来切换usb功能,例如adb shell setprop sys.usb.config mtp,adb
可以切换到mtp功能。 - 如果通过
sys.usb.config
属性切换功能成功,那么sys.usb.state
属性值就与sys.usb.config
属性值一样。也就是说sys.usb.state
代表usb的实际功能的值。所以,可以通过比较这两个属性值来判断usb所有功能是否切换成功,如果成功了,mCurrentFunctionsApplied的值为1,否则为0。
第三步,读取了当前usb状态,并且做了一次更新操作。更新操作会发送相关通知,以及发送广播,但是现在处理服务创建阶段,这个操作都无法执行,因此这里不做分析。但是当处理系统就绪阶段或系统启动完毕阶段,就可以做相应的操作,在后面的分析中可以看到。
系统就绪阶段
根据前面的代码,在系统就绪阶段,会调用UsbService的systemRead()方法,然后转到UsbDeviceManager的systemRead()方法
public void systemReady() {
// 注册一个关于屏幕状态的回调,有两个方法
LocalServices.getService(ActivityTaskManagerInternal.class).registerScreenObserver(this);
mHandler.sendEmptyMessage(MSG_SYSTEM_READY);
}
首先注册了一个关于屏幕的回调,这个回调用于处理在安全锁屏下,设置usb的功能。但是这个功能好像处于开发阶段,只能通过adb shell
命令操作,通过输入adb shell svc usb
可以查看使用帮助。
接下来,发送了一个消息MSG_SYSTEM_READY
,我们来看下这个消息是如何处理的
case MSG_SYSTEM_READY:
// 获取到notification服务接口
mNotificationManager = (NotificationManager)
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
// 向adb service注册一个回调,用于状态adb相关的状态
LocalServices.getService(
AdbManagerInternal.class).registerTransport(new AdbTransport(this));
// Ensure that the notification channels are set up
if (isTv()) {
// ...
}
// 设置系统就绪的标志位
mSystemReady = true;
// 此时系统还没有启动完成,这里没有做任何事
// 这应该是历史原因造成的代码冗余
finishBoot();
break;
系统启动完毕阶段
现在来看下最后一个阶段,系统启动完毕阶段。根据前面的代码,会调用UsbService的bootcompleted()方法,然后调用UsbDeviceManager的bootcompleted()方法
public void bootCompleted() {
mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
}
只是发送了一条消息,看下消息如何处理的
case MSG_BOOT_COMPLETED:
// 设置系统启动完成的标志
mBootCompleted = true;
finishBoot();
break;
finishBoot()方法
很简单,设置了一个启动标志,然后就调用finishBoot()方法完成最后的任务
protected void finishBoot(int operationId) {
if (mBootCompleted && mCurrentUsbFunctionsReceived && mSystemReady) {
if (mPendingBootBroadcast) {
updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions));
mPendingBootBroadcast = false;
}
if (!mScreenLocked
&& mScreenUnlockedFunctions != UsbManager.FUNCTION_NONE) {
setScreenUnlockedFunctions(operationId);
} else {
setEnabledFunctions(UsbManager.FUNCTION_NONE, false, operationId);
}
if (mCurrentAccessory != null) {
mUsbDeviceManager.getCurrentSettings().accessoryAttached(mCurrentAccessory);
broadcastUsbAccessoryHandshake();
} else if (mPendingBootAccessoryHandshakeBroadcast) {
broadcastUsbAccessoryHandshake();
}
mPendingBootAccessoryHandshakeBroadcast = false;
updateUsbNotification(false);
updateAdbNotification(false);
updateUsbFunctions();
}
}
这个函数名为 finishBoot
,在 Android 系统中用于完成设备启动过程中与 USB 相关的操作。该函数确保在设备启动完成后,USB 功能配置正确,并处理与 USB 相关的任务。下面是函数的主要功能和操作步骤:
函数功能:
finishBoot
函数在设备启动完成后执行,并根据当前的系统状态和 USB 状态做出相应的处理。函数的执行依赖于以下三个条件:
mBootCompleted
:表示设备启动已完成。mCurrentUsbFunctionsReceived
:表示当前 USB 功能已经接收并处理。mSystemReady
:表示系统已准备好(可能指系统服务或其他依赖已启动)。
主要操作步骤:
-
广播 USB 状态更新:
- 如果
mPendingBootBroadcast
为true
,表示有挂起的 USB 状态广播需要发送。函数会调用updateUsbStateBroadcastIfNeeded
发送广播,更新 USB 状态,然后将mPendingBootBroadcast
设置为false
。
- 如果
-
设置屏幕解锁后的 USB 功能:
- 如果设备屏幕未锁定 (
mScreenLocked
为false
),并且mScreenUnlockedFunctions
的值不为UsbManager.FUNCTION_NONE
(即有特定功能要在解锁后启用),则调用setScreenUnlockedFunctions
设置这些功能。 - 否则,调用
setEnabledFunctions
,将 USB 功能设置为UsbManager.FUNCTION_NONE
。
- 如果设备屏幕未锁定 (
-
处理 USB 附件:
- 如果当前有连接的 USB 附件 (
mCurrentAccessory
不为null
),则通知 USB 设备管理器(mUsbDeviceManager
)附件已连接,并广播 USB 附件握手事件。 - 如果没有连接的 USB 附件但有挂起的握手广播 (
mPendingBootAccessoryHandshakeBroadcast
为true
),则广播 USB 附件握手事件。
- 如果当前有连接的 USB 附件 (
-
更新状态和通知:
- 将
mPendingBootAccessoryHandshakeBroadcast
设置为false
,表示不再有挂起的 USB 附件握手广播。 - 调用
updateUsbNotification(false)
更新 USB 相关的通知。 - 调用
updateAdbNotification(false)
更新 ADB 相关的通知。 - 调用
updateUsbFunctions()
更新当前的 USB 功能配置。
- 将
如果现在手机没有通过USB线连接电脑,那么第一步的发送USB状态广播,第三步的USB通知,第四步adb通知,都无法执行。唯一能执行的就是第二步,设置USB功能为NONE。
setEnabledFunctions函数:
OK,现在终于到最关键的一步,设置USB功能,它调用的是setEnabledFunctions()
方法。这个方法本身是一想抽象方法,在我的项目中,实现类为UsbHandlerLegacy
/**
* Evaluates USB function policies and applies the change accordingly.
*/
protected abstract void setEnabledFunctions(long functions,
boolean forceRestart, int operationId);
protected void setEnabledFunctions(long functions, boolean forceRestart, int operationId) {
if (DEBUG) {
Slog.d(TAG, "setEnabledFunctionsi " +
"functions=" + functions +
", forceRestart=" + forceRestart +
", operationId=" + operationId);
}
if (mCurrentGadgetHalVersion < UsbManager.GADGET_HAL_V1_2) {
if ((functions & UsbManager.FUNCTION_NCM) != 0) {
Slog.e(TAG, "Could not set unsupported function for the GadgetHal");
return;
}
}
if (mCurrentFunctions != functions
|| !mCurrentFunctionsApplied
|| forceRestart) {
Slog.i(TAG, "Setting USB config to " + UsbManager.usbFunctionsToString(functions));
mCurrentFunctions = functions;
mCurrentFunctionsApplied = false;
// set the flag to false as that would be stale value
mCurrentUsbFunctionsRequested = false;
boolean chargingFunctions = functions == UsbManager.FUNCTION_NONE;
functions = getAppliedFunctions(functions);
// Set the new USB configuration.
setUsbConfig(functions, chargingFunctions, operationId);
if (mBootCompleted && isUsbDataTransferActive(functions)) {
// Start up dependent services.
updateUsbStateBroadcastIfNeeded(functions);
}
}
}
首先判断要设置的新的USB功能的数据是否是解锁状态,只有MTP和PTP模式的数据是解锁状态,这是为何你能在设置MTP或PTP模式后,在PC端能看到手机中的文件,然而这个文件只是手机内存中文件的映射,并不是文件本身。
然后处理数据解锁状态改变的情况,如果是,那么会更新状态,更新usb广播,然后最重要的是设置forceRestart
变量的值为true
,这个变量代表要强制重启usb功能。
最后,设置新usb功能。如果失败了,就回退。现在来看下trySetEnabledFunctions()
方法如何设置新功能
@Override
protected void setEnabledFunctions(long functions, boolean forceRestart, int operationId) {
if (DEBUG) {
Slog.d(TAG, "setEnabledFunctionsi " +
"functions=" + functions +
", forceRestart=" + forceRestart +
", operationId=" + operationId);
}
if (mCurrentGadgetHalVersion < UsbManager.GADGET_HAL_V1_2) {
if ((functions & UsbManager.FUNCTION_NCM) != 0) {
Slog.e(TAG, "Could not set unsupported function for the GadgetHal");
return;
}
}
if (mCurrentFunctions != functions
|| !mCurrentFunctionsApplied
|| forceRestart) {
Slog.i(TAG, "Setting USB config to " + UsbManager.usbFunctionsToString(functions));
mCurrentFunctions = functions;
mCurrentFunctionsApplied = false;
// set the flag to false as that would be stale value
mCurrentUsbFunctionsRequested = false;
boolean chargingFunctions = functions == UsbManager.FUNCTION_NONE;
functions = getAppliedFunctions(functions);
// Set the new USB configuration.
setUsbConfig(functions, chargingFunctions, operationId);
if (mBootCompleted && isUsbDataTransferActive(functions)) {
// Start up dependent services.
updateUsbStateBroadcastIfNeeded(functions);
}
}
}
代码功能概述:
setEnabledFunctions
的主要作用是在满足一定条件的情况下,将设备的 USB 功能配置为指定的功能集。如果这些功能与当前功能配置不同,或者需要强制重新启动 USB 堆栈,它将应用新的配置并更新相关状态。
主要操作步骤:
- 调试信息输出:
- 如果
DEBUG
标志为真,则通过Slog.d
输出调试信息,包括传入的functions
、forceRestart
和operationId
的值。
- 如果
- Gadget HAL 版本检查:
- 如果当前的
GadgetHal
版本低于UsbManager.GADGET_HAL_V1_2
,并且传入的functions
中包含UsbManager.FUNCTION_NCM
(Network Control Model),则记录错误日志并返回,因为该版本不支持NCM
功能。
- 如果当前的
- 判断是否需要重新配置 USB 功能:
- 重新配置的条件包括:当前功能配置
mCurrentFunctions
与传入的functions
不同,或者当前功能配置尚未应用 (mCurrentFunctionsApplied
为false
),或者forceRestart
标志为真。 - 如果满足上述条件之一,表示需要重新设置 USB 功能。
- 重新配置的条件包括:当前功能配置
- 设置 USB 功能配置:
- 更新
mCurrentFunctions
为传入的functions
,并将mCurrentFunctionsApplied
设置为false
,表示新的配置尚未应用。 - 将
mCurrentUsbFunctionsRequested
设置为false
,表示当前的 USB 功能请求状态为过时值,需要重新设置。
- 更新
- 检查是否为充电功能:
- 如果
functions
等于UsbManager.FUNCTION_NONE
,表示设备处于仅充电状态。 - 调用
getAppliedFunctions(functions)
获取实际应用的 USB 功能配置。
- 如果
- 应用新的 USB 配置:
- 调用
setUsbConfig(functions, chargingFunctions, operationId)
方法,应用新的 USB 配置。 chargingFunctions
参数指示是否为仅充电功能。
- 调用
- 更新 USB 状态:
- 如果设备已经完成启动 (
mBootCompleted
为真) 且 USB 数据传输功能被激活(即functions
包含数据传输功能),则调用updateUsbStateBroadcastIfNeeded(functions)
方法,启动相关服务并更新 USB 状态广播。
- 如果设备已经完成启动 (
trySetEnabledFunctions函数:
private boolean trySetEnabledFunctions(long usbFunctions, boolean forceRestart) {
String functions = null;
if (usbFunctions != UsbManager.FUNCTION_NONE) {
functions = UsbManager.usbFunctionsToString(usbFunctions);
}
mCurrentFunctions = usbFunctions;
if (functions == null || applyAdbFunction(functions)
.equals(UsbManager.USB_FUNCTION_NONE)) {
functions = UsbManager.usbFunctionsToString(getChargingFunctions());
}
functions = applyAdbFunction(functions);
String oemFunctions = applyOemOverrideFunction(functions);
if (!isNormalBoot() && !mCurrentFunctionsStr.equals(functions)) {
setSystemProperty(getPersistProp(true), functions);
}
if ((!functions.equals(oemFunctions)
&& !mCurrentOemFunctions.equals(oemFunctions))
|| !mCurrentFunctionsStr.equals(functions)
|| !mCurrentFunctionsApplied
|| forceRestart) {
mCurrentFunctionsStr = functions;
mCurrentOemFunctions = oemFunctions;
mCurrentFunctionsApplied = false;
/**
* Kick the USB stack to close existing connections.
*/
setUsbConfig(UsbManager.USB_FUNCTION_NONE);
if (!waitForState(UsbManager.USB_FUNCTION_NONE)) {
Slog.e(TAG, "Failed to kick USB config");
return false;
}
/**
* Set the new USB configuration.
*/
setUsbConfig(oemFunctions);
if (mBootCompleted
&& (containsFunction(functions, UsbManager.USB_FUNCTION_MTP)
|| containsFunction(functions, UsbManager.USB_FUNCTION_PTP))) {
/**
* Start up dependent services.
*/
updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions));
}
if (!waitForState(oemFunctions)) {
Slog.e(TAG, "Failed to switch USB config to " + functions);
return false;
}
mCurrentFunctionsApplied = true;
}
return true;
}
我把这里的逻辑分为了三步.
第一步,把待设置的USB功能转化为字符串,有两种情况
- 如果新功能为
FUNCTION_NONE
,那么转化后的值从persist.sys.usb.config
获取,如果获取值为NONE,就判断adb是否开启,如果开启了,转化后的值为adb,如果没有开启,转化后的值为mtp。前面分析说过,persist.sys.usb.config
主要包含用于判断adb是否开启在值,然后还包含一些厂商定制且用于测试目的的功能。例如,高通项目,这个值可能为adb,diag
,这个diag就是高通自己的功能。 - 如果新功能不为
FUNCTION_NONE
,把直接转化。例如新功能为FUNCTION_MTP
,那么转化后的字符串为mtp
。
转化字符串后,根据adb是否开启,来决定从转化后的字符串中增加adb属性还是移除adb属性。
第二步,获取oem覆盖的功能。前面说过,默认系统是没有使用覆盖功能,所以这里获取的覆盖后的功能与新功能转化后的字符串是一样的。
我在分析代码的时候,脑海里一直在想,这个覆盖功能如何使用。根据我的对代码的分析,唯一的规则就是主要功能不能覆盖。举个例子,如果新设置的功能的字符串为mtp,那么覆盖数组中的其中一项元素的值应该是normal:mtp:mtp,diag
,其中nomral表示正常启动,mtp表示原始的功能,mtp,diag表示覆盖后的功能,请注意,覆盖后的功能一定要保存mtp这个主功能。当然这只是我个人对代码分析得出的结论,还没验证。这里我要吐槽一下这个功能的设计者,难道写个例子以及注意事项就这么难吗?
第三步,设置新功能。不过设置新功能前,首先要断开已经存在的连接,然后再设置新功能。设置新功能是通过setUsbConfig()
方法,来看下实现
private void setUsbConfig(String config) {
// 设置sys.usb.config
setSystemProperty(USB_CONFIG_PROPERTY, config);
}
震惊!原来就是设置sys.usb.config的属性值,还记得吗,在前面的分析中,也解释过这个属性值,它就是代表当前设置的usb功能,从这里就可以得到证明。
这其实也在提示我们,其实可以通过adb shell setprop
命令设置这个属性,从而控制usb功能的切换。在实际的工作中,屡试不爽。
设置这个属性后如何判断设置成功了呢?这就是waitForState()
所做的
private boolean waitForState(String state) {
String value = null;
for (int i = 0; i < 20; i++) {
// 获取sys.usb.stat值
value = getSystemProperty(USB_STATE_PROPERTY, "");
// 与刚才设置的sys.usb.config属性值相比较
if (state.equals(value)) return true;
SystemClock.sleep(50);
}
return false;
}
说实话,我看到这段代码,确实吃了一鲸! 这段代码在1秒内执行20次,获取sys.usb.state
属性值,然后与设置的sys.usb.config
属性值相比较,如果相等就表示功能设置成功。
还记得吗?在前面的分析中,我也解释过sys.usb.state
属性的作用,它代表usb实际的功能,从这里就可以得到验证。
那么现在有一个问题,底层如何实现usb功能切换呢?当然是响应属性sys.usb.config
属性改变
on property:sys.usb.config=mtp,adb && property:sys.usb.configfs=0
# 先写0
write /sys/class/android_usb/android0/enable 0
# 写序列号
write /sys/class/android_usb/android0/iSerial ${ro.serialno}
# 写vid, pid
write /sys/class/android_usb/android0/idVendor 05C6
write /sys/class/android_usb/android0/idProduct 9039
# 设置USB功能为mtp,adb
write /sys/class/android_usb/android0/functions mtp,adb
# 再写1启动功能
write /sys/class/android_usb/android0/enable 1
# 启动adb
start adbd
# 设置 sys.usb.state属性值为sys.usb.config的属性值
setprop sys.usb.state ${sys.usb.config}
根据注释,你应该就可以很清楚了解这个过程了。
so, 你以为这就完了吗?还没呢,如果新设置的功能是MTP或PTP,那么还要更新广播呢。
protected void updateUsbStateBroadcastIfNeeded(long functions) {
// send a sticky broadcast containing current USB state
Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
| Intent.FLAG_RECEIVER_FOREGROUND);
// 保存了usb状态值
intent.putExtra(UsbManager.USB_CONNECTED, mConnected);
intent.putExtra(UsbManager.USB_HOST_CONNECTED, mHostConnected);
intent.putExtra(UsbManager.USB_CONFIGURED, mConfigured);
intent.putExtra(UsbManager.USB_DATA_UNLOCKED,
isUsbTransferAllowed() && isUsbDataTransferActive(mCurrentFunctions));
// 保存了要设置的新功能的值,例如设置的是MTP,那么参数的key为mtp,值为true
long remainingFunctions = functions;
while (remainingFunctions != 0) {
intent.putExtra(UsbManager.usbFunctionsToString(
Long.highestOneBit(remainingFunctions)), true);
remainingFunctions -= Long.highestOneBit(remainingFunctions);
}
// 如果状态没有改变,就不发送广播
if (!isUsbStateChanged(intent)) {
return;
}
// 注意这里发送的是一个sticky广播
sendStickyBroadcast(intent);
mBroadcastedIntent = intent;
标签:FUNCTION,functions,USB,UsbManager,代码,new,UsbDeviceManager,Android,usb
From: https://www.cnblogs.com/linhaostudy/p/18368396