android 2.3 wifi (二)

 

7.       Ad hoc的支持

添加ad hoc的支持有两种方式,改wpa_supplicant和改Android Framework wpa_supplicant的原理和方法请参考http://www.xda-developers.com/android/android-ad-hoc-wireless-network-support/, 这种方法不推荐, 不是解决问题的根本。下面是改Android Framework的方法。

Android Framework中添加adhoc支持很简单, 可能只需要改一行代码(当然还没经过测试) 如下:

List<ScanResult> results = mWifiManager.getScanResults();

        if (results != null) {

            for (ScanResult result : results) {

                // Ignore hidden and ad-hoc networks.

                if (result.SSID == null || result.SSID.length() == 0 ||

                        result.capabilities.contains("[IBSS]")) {

                    continue;

                }

 

                boolean found = false;

                for (AccessPoint accessPoint : accessPoints) {

                    if (accessPoint.update(result)) {

                        found = true;

                    }

                }

                if (!found) {

                    accessPoints.add(new AccessPoint(this, result));

                }

            }

        }

上面一段代码在Settings应用的WifiSettings类里发生在wpa_supplicant扫描ap结束时||result.capabilities.contains("[IBSS]")去掉即可支持adhoc

可见google是故意禁了ad hoc的功能。 那么总有原因 下面摘自某论坛

What you say is true - it is relatively easy to support ad-hoc networks. I also appreciate that it sucks if you have to rely on ad-hoc wifi and you own an Android device.
However, there are good reasons as to why Android, or any OS for that matter, doesn't support it.

Ad-hoc networks are inherently insecure as they require no authentication for people joining the network. Ad-hoc networks were only ever intended to be used for very short term spontaneous and informal networks. "Short term", in this context, means the time it takes you to purchase a proper wireless access point.

Ad-hoc networks are highly discouraged, as not only are they insecure, but they interfere with people using the proper, secure, and recommended, infrastructure WiFi networks.

These facts probably demotivated Google from implementing support for it.

As most broadband (Cable or ADSL) routers come with WiFi these days, and as a lot of the rest of us (like me) use stand-alone wireless access points, the requirement for Ad-Hoc support is low. Also, as the phones that run Android have 3G, Edge, and GPRS support the need is even lower for Android users. As such, you can probably see why Google didn't bother - there are other features that more people "require", and so Google probably concentrated on adding those.

 

TODO: 怎样创建ad hoc网络让其它设备连进来?

8.       wifi direct

Wifi direct又叫wifi p2p, 是一种新型的技术, 用来取代蓝牙, 具有速度快连接方便的特点。 不过目前Android2.3还并不支持, 但应该会很快有支持。 下面是一些资料。

http://wireless.kernel.org/en/developers/p2p

 

Android4.0已经支持wifi direct api已经导出。

9.       Soft ap支持

Ap可以为游戏应用提供联机对战的功能, 也可以基于软ap实现网络共享, 即连接到软Ap上的设备可以共享软Ap设备的网络, 比如手机可以作为软Ap 笔记本连进来就可以通过手机的3g上网。

支持soft ap当然首先要驱动支持, 初步调研结论是ar6k驱动可以支持soft ap 后续还需确认。

Android 2.2(froyo)开始支持soft ap 可以在Settings程序里设置soft ap功能, 如下图:

android 2.3 wifi (二)_第1张图片

       但是我们在模拟器上并无上面的界面, 是在运行时会调用ConnectivityManager.isTetheringSupported()函数来判断系统是否支持Tethering 如果不支持Tethering就隐藏上面界面。

       开启Soft ap功能在Settings程序的WifiApEnabler. onPreferenceChange里, 设置soft apWifiApDialog.onClick里。它们依赖WifiManager的如下接口:

 

    public boolean setWifiApEnabled(WifiConfiguration wifiConfig, booleanenabled)

    

    public int getWifiApState()

    

    public WifiConfiguration getWifiApConfiguration()

    

    public boolean setWifiApConfiguration(WifiConfiguration wifiConfig)

       WifiManager调用WifiService实现的功能, WifiService最终调用NetworkManagementService.startAccessPoint函数, 如下:

public void startAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface)

                                                                                      throwsIllegalStateException {

        mContext.enforceCallingOrSelfPermission(

                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");

        mContext.enforceCallingOrSelfPermission(

                android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");

        try {

            mConnector.doCommand(String.format("softap stop " + wlanIface));

            mConnector.doCommand(String.format("softap fwreload " + wlanIface + " AP"));

            mConnector.doCommand(String.format("softap start " + wlanIface));

            if (wifiConfig == null) {

                mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface));

            else {

                

                String str = String.format("softap set " + wlanIface + " " + softapIface +

                                           " %s %s %s", convertQuotedString(wifiConfig.SSID),

                                           wifiConfig.allowedKeyManagement.get(KeyMgmt.WPA_PSK) ?

                                           "wpa2-psk" : "open",

                                           convertQuotedString(wifiConfig.preSharedKey));

                mConnector.doCommand(str);

            }

            mConnector.doCommand(String.format("softap startap"));

        catch (NativeDaemonConnectorException e) {

            throw new IllegalStateException("Error communicating to native daemon to start softap", e);

        }

    }

 

       NetworkManagementService顾名思义是Android系统的网络管理服务, 负责比较特殊的网络的设置(比如网络共享(Tether)和网络地址转换(Nat)ip 转发(ip forwording))和向上层通知网络相关的事件。mConnector是一个NativeDaemonConnector 这里用来和系统的netd守护进程通信。NetworkManagementService的好多功能都是通过Netd实现的。 Netd的代码在“android sources/system/netd里。Netdsoftap控制的功能在“android sources/system/netd/SoftapController.{h,cpp}里, 是通过wireless extention定义的SIOCGIWPRIV来调用网卡驱动的ap功能。 如果具体网卡驱动提供的soft ap接口不同, SoftapController的代码就需要改。比如ar6k的驱动厂家提供了hostapd来控制ap 就需要改SoftapController来适配hostapd提供的接口。

10.   Wifi Tethering支持

Settings程序里看不到关于Wifi Tethering的任何代码, 着实让我迷惑了一下。 原来开启soft ap功能后就会自动启动wifi tethering com.android.server.connectivity.Tethering类向NetworkManagementService(NetworkManagementService通过netd来监听, netdnetlink socket监听内核热插拔事件)类注册了一个Observer来监听Interfaceadd remove change的信息。 当使能soft ap时, 会以soft ap模式加载驱动, 此时驱动会发出热插拔事件。 Tethering类里面跑了两种状态机, 一个TetherMasterSM nTetherInterfaceSM(每个tetherable interface对应一个) 添加Interface时就会启动一个TetherInterfaceSM状态机, 并进入Initial状态, 发出ConnectivityManager.ACTION_TETHER_STATE_CHANGED广播。 WifiService收到广播后调用ConnectivityService.tethering(inf)函数, TetherInterfaceSM发送CMD_TETHER_REQUESTED命令, 进入tethered状态。

UpstreamIface(比如现在不共享以太网而变为共享3g网络)发生变化时, TetherMasterSM会通知所有TetherInterfaceSM改变nat

TetherMasterSM初始阶段UpstreamIface的选择是根据从NetworkManagementServicem获得所有Ingerface,能匹配上com.android.internal.R.array.config_tether_upstream_regexs(base.core.res.res.values.configs中定义, 原始为空需要根据实际情况来改)的第一个状态为upinterface即被选为UpstreamIface

运行时UpstreamIface也可能变化, Tethering类监听ConnectivityManager.CONNECTIVITY_ACTION事件(当网络连接变化时由ConnectivityService发出) 当收到时给TetherMasterSMTetherMasterSM.CMD_UPSTREAM_CHANGED消息。 TetherMasterSM收到后重新选择UpstreamIface,并向所有TetherInterfaceSM发送TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED事件来用新的UpstreamIface重启Nat

Tethering原理如下:

NetworkManagementService.setIpForwardingEnabled(true)

NetworkManagementService.startTethering(mDhcpRange)// 启动dnsmasq(负责dhcpdns forwarding)

NetworkManagementService. setDnsForwarders(mDnsServers)//通过给dnsmasq发命令来设置dns服务器

NetworkManagementService.enableNat(String internalInterface, String externalInterface)//启动nat(网络地址转换)

11.   Usb Tethering支持

何谓usb tethering 这里举个例子, 我们的设备连上了wifi 此时将设备通过usb连接到pc pc即可以共享我们设备的wifi网络, 可以将我们的设备看做是一块usb接口的无线网卡。

Wifi Tethering从用户的角度来看是手动启动(通过Settings使能soft ap) 但从原理上看是自动启动, 使能soft apNetworkManagementService收到interfaceAdded信号后便自动启动wifi tethering

usb tethering则不同, 无论从用户的角度还是从原理的角度都是手动启动。 当设备通过usb连上pc时,NetworkManagementService会收到interfaceAdded信号。 不过并不能立刻开启tethering 因为连上pc的目的并不只有一个, 用户想要的可能是读写设备的sd卡。所以Usb Tethering会很关心Usb.ACTION_USB_STATEIntent.ACTION_MEDIA_SHAREDIntent.ACTION_MEDIA_UNSHARED事件。 只有当usb连上并且media unshared的情况下才可以usb tethering tethering过程中收到Intent.ACTION_MEDIA_SHARED Tethering类和WifiSettings类都会有相应的动作。

手动在Settings里启动UsbTethering时, 会调用ConnectivityService.Tethering(inf)函数开启usb tethering

原理如下:

NetworkManagementService.setIpForwardingEn cpRange)// 启动dnsmasq(负责dhcpdns forwarding)

NetworkManagementService.setDnsForwarders(mDnsServers)//通过给dnsmasq发命令来设置dns服务器

Tethering.configureUsbIface(true)//配置usb interface ip netmask up

Tethering.enableUsbRndis(true)//开启Usb Rndis(Remote Network Driver Interface Specification),使设备变成usb无线网卡

NetworkManagementService.enableNat(String internalInterface, String externalInterface)//启动nat(网络地址转换)abled(true)

NetworkManagementService.startTethering(mDh

另外补充一点,如果是Windows还需要安装usb tethering驱动才可以: http://www.android.com/tether

12.   Reverse usb Tethering

何谓Reverse usb Tetheringusb Tetheringpc可以通过我们的设备上网,  Reverse usb Tethering是设备可以通过Pc上网, 只要usb线连上pc

目前Android不支持, Framework只改Settings程序应该就可以添加支持, 在驱动层也需要支持, 可能只是编译内核时打开某些选项而已, 待确定。

未完待续……

13.   Ethernet Tethering

所谓Ethernet Tethering Pc机通过网线连接到设备时即可共享设备的wifi3g网络。

目前Android不支持,有线网卡connected3gwifi都会禁掉。

14.   需要改动的地方

针对5201平台(ar6k驱动) 我们需要对framework做如下修改。

 

基本:

android sources\hardware\libhardware_legacy\wifi\wifi.c:驱动名称

l         Adhoc支持:

Settings应用的WifiSettings类:将隐藏adhoc网络的代码去掉

l         Softap支持:

android sources/system/netd/SoftapController.{h,cpp}:适配到hostapd

android sources\hardware\libhardware_legacy\wifi\wifi.c:驱动的参数决定模式(ap or station)

com.android.server.connectivity: ip default dns

l         Wifi Tethering支持:

base.core.res.res.values.configs 根据平台实际情况修改config_tether_upstream_regexsarray.config_tether_wifi_regexs,  array.config_tether_usb_regexs

l         Usb Tethering支持:

base.core.res.res.values.configs:根据平台实际情况修改array.config_tether_usb_regexs

15.   测试

驱动的测试可以借助工具比如wpa_cli 当我们改好framework代码后, 怎样确保它能工作呢?Android framework针对ConnectivityManagerWifiManager的单元测试,位于core.test.ConnectivityManagerTest中,  都是依赖于真实硬件的, 模拟器做不了。 当我们改了代码后, 可以运行这些单元测试来确保我们的改动。

运行WifiConnectionTest命令:

adb shell am instrument -e class  \

     com.android.connectivitymanagertest.functional.WifiConnectionTest  \

-w com.android.connectivitymanagertest/.ConnectivityManagerTestRunner

       运行WifiSoftAPTest命令:

adb shell am instrument \

-w com.android.connectivitymanagertest/.ConnectivityManagerUnitTestRunner

    详情看代码。

16.   调试中遇到的问题

系统中多个Dhcpcd进程存在, 经查是setproperty(“ctl.stop”, “dhcpcd_eth0”)不能停掉Dhcpcd进程, 以至于下次启动时又会创建新的Dhcpcd进程。 最后发现是启动dhcp参数问题导致,应用-B参数不让dpcp以daemon形式运行即可。

你可能感兴趣的:(android,String,网络,单元测试,interface,DNS服务器)