赞
踩
请转载的朋友表明出处:
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
- <string-array translatable="false" name="config_tether_usb_regexs">
- <item>"usb\\d"</item>
- <item>"rndis\\d"</item>
- </string-array>
后话:
总结的时候是在一个低版本的平台中发现的问题,所以就总结了低版本的code,我看了下 android 7.1 的版本,逻辑上做了稍微的调整,功能上设计是一样的,最终同样调用到的还是Tethering.java 中的setUsbTethering。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。