usb 网络共享无法选择
请转载的朋友表明出处:
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 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 中做配置,如下:
- "usb\\d"
- "rndis\\d"
这样,只要驱动给出来的interface 是rndis0 即可,bug 就算解决了
后话:
总结的时候是在一个低版本的平台中发现的问题,所以就总结了低版本的code,我看了下 android 7.1 的版本,逻辑上做了稍微的调整,功能上设计是一样的,最终同样调用到的还是Tethering.java 中的setUsbTethering。
更多相关文章
- [Fuzz]Android模糊测试
- 获取MD5指纹的时候遇到错误
- 将android的adb命令工具作用于mac全局
- JNI和NDK编程(一)
- Android(安卓)SDK Manager浅析
- Android中判断当前API的版本号方法
- Android桌面小控件appwidget的故事Ⅰ
- Android应用程序四大组件之使用AIDL如何实现跨进程调用Service
- 使用Html在EditText中任意位置插入图片并正确显示