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<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。



















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

私房菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值