usb 网络共享无法选择

时间:2022-01-06 16:09:06

请转载的朋友表明出处:

http://blog.csdn.net/shift_wwx/article/details/77941434


最近碰到一个bug,设置中usb 网络共享无法选择,跟了一下code 后总结一下(版本是android 4.4)


Setting 中详细code 不做总结,主要是最后调用的地方:

(code 路径是:packages/app/Settings/****/TetherSettings.java)

    private void setUsbTethering(boolean enabled) {
ConnectivityManager cm =
(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
mUsbTether.setChecked(false);
if (cm.setUsbTethering(enabled) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
mUsbTether.setSummary(R.string.usb_tethering_errored_subtext);
return;
}
mUsbTether.setSummary("");
}


最终调用到cm.setUsbTethering(enabled):

(code 路径是: frameworks/base/services/****/ConnectivityService.java)

    public int setUsbTethering(boolean enable) {
enforceTetherChangePermission();
if (isTetheringSupported()) {
return mTethering.setUsbTethering(enable);
} else {
return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
}
}


下一步是Tethering.java:

(code 路径是 frameworks/base/services/****/Tethering.java)

    public int setUsbTethering(boolean enable) {
if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);

synchronized (mPublicSync) {
if (enable) {
if (mRndisEnabled) {
tetherUsb(true);
} else {
mUsbTetherRequested = true;
usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
}
} else {
tetherUsb(false);
if (mRndisEnabled) {
usbManager.setCurrentFunction(null, false);
}
mUsbTetherRequested = false;
}
}
return ConnectivityManager.TETHER_ERROR_NO_ERROR;
}

---->

    private void tetherUsb(boolean enable) {
if (VDBG) Log.d(TAG, "tetherUsb " + enable);

String[] ifaces = new String[0];
try {
ifaces = mNMService.listInterfaces();
} catch (Exception e) {
Log.e(TAG, "Error listing Interfaces", e);
return;
}

final String usbSysctlKey = "sys.usb.tethering";
SystemProperties.set(usbSysctlKey, "false");

if (enable) {
SystemProperties.set(usbSysctlKey, "true");
}

for (String iface : ifaces) {
Log.d(TAG, "iface: " + iface);
if (isUsb(iface)) {
int result = (enable ? tether(iface) : untether(iface));
if (result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
return;
}
}
}
Log.e(TAG, "unable start or stop USB tethering");
}

看到这里,大概可以猜到无法成功选择的原因:

1、ifaces = mNMService.listInterfaces(); 出现异常,catch 中直接return

2、同样 1 这句话,可能获取的ifaces 不存在(是否存在,可以在下面的循环中加上log,贴出来的code 中已经加上log)

3、循环中 isUsb(iface) 返回为false


对于上面的三个问题,我一一做了排查,最后发现是isUsb这个函数出现的问题:

    private boolean isUsb(String iface) {
synchronized (mPublicSync) {
for (String regex : mTetherableUsbRegexs) {
if (iface.matches(regex)) return true;
}
return false;
}
}
也就是iface 必须要是符合一定的规则,而变量mTetherableUsbRegexs 就是所谓的规则。


找到mTetherableUsbRegexs 定义个赋值的地方:

    void updateConfiguration() {
String[] tetherableUsbRegexs = mContext.getResources().getStringArray(
com.android.internal.R.array.config_tether_usb_regexs);
String[] tetherableWifiRegexs = mContext.getResources().getStringArray(
com.android.internal.R.array.config_tether_wifi_regexs);
String[] tetherableBluetoothRegexs = mContext.getResources().getStringArray(
com.android.internal.R.array.config_tether_bluetooth_regexs);

int ifaceTypes[] = mContext.getResources().getIntArray(
com.android.internal.R.array.config_tether_upstream_types);
Collection<Integer> upstreamIfaceTypes = new ArrayList();
IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
try {
int activeNetType = cm.getActiveNetworkInfo().getType();
for (int i : ifaceTypes) {
if(i == activeNetType) {
upstreamIfaceTypes.add(new Integer(i));
}
}
} catch (Exception e) {
Log.d(TAG, "Exception adding default nw to upstreamIfaceTypes: " + e);
}
for (int i : ifaceTypes) {
if(!upstreamIfaceTypes.contains(new Integer(i))) {
upstreamIfaceTypes.add(new Integer(i));
}
}

synchronized (mPublicSync) {
mTetherableUsbRegexs = tetherableUsbRegexs;
mTetherableWifiRegexs = tetherableWifiRegexs;
mTetherableBluetoothRegexs = tetherableBluetoothRegexs;
mUpstreamIfaceTypes = upstreamIfaceTypes;
}

// check if the upstream type list needs to be modified due to secure-settings
checkDunRequired();
}
最终知道变量mTetherableUsbRegexs 来源于config:

com.android.internal.R.array.config_tether_usb_regexs


最终确定的是这个config 必须要配置,android 源生是没有这样配置的,需要在overlay 中做配置,如下:

    <string-array translatable="false" name="config_tether_usb_regexs">                                
<item>"usb\\d"</item>
<item>"rndis\\d"</item>
</string-array>

这样,只要驱动给出来的interface 是rndis0 即可,bug 就算解决了



后话:

总结的时候是在一个低版本的平台中发现的问题,所以就总结了低版本的code,我看了下 android 7.1 的版本,逻辑上做了稍微的调整,功能上设计是一样的,最终同样调用到的还是Tethering.java 中的setUsbTethering。