请转载的朋友表明出处:

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。



















更多相关文章

  1. [Fuzz]Android模糊测试
  2. 获取MD5指纹的时候遇到错误
  3. 将android的adb命令工具作用于mac全局
  4. JNI和NDK编程(一)
  5. Android(安卓)SDK Manager浅析
  6. Android中判断当前API的版本号方法
  7. Android桌面小控件appwidget的故事Ⅰ
  8. Android应用程序四大组件之使用AIDL如何实现跨进程调用Service
  9. 使用Html在EditText中任意位置插入图片并正确显示

随机推荐

  1. 正确设置Android(安卓)Studio代理配置
  2. Android开发之初探音频的播放
  3. 《Android开发艺术探索》第十一章重点笔
  4. [Android]模拟器无法启动:Waiting for HOM
  5. android——读写内部和外部存储方法
  6. Android24_Service初步
  7. Android(安卓)网络请求框架Retrofit2.0使
  8. Android中自定义底部弹出框ButtomDialog
  9. Android(安卓)网络应用--Apache HttpClie
  10. [转]android学习总结----Activity view