android 2.3 ethernet

来源:互联网 发布:睡觉一直说梦话知乎 编辑:程序博客网 时间:2024/04/29 21:46

1.    前言

2.    本文目的

3.    网络管理模块的架构

4.    情景分析

4.1.     情景一

4.2.     情景2

5.    添加Ethernet支持所需做的添加和改动

6.    NetWorkUtils

7.    EthernetNative

8.    疑惑

9.    android 2.3.4 for mips添加以太网支持

10.   TODO


1.       前言

       用过Android手机的人都知道, 如果附近有wifi信号, 当使能Wifi的时候, 系统就会通过wifi联网,wifi信号消失或者你手动禁止wifi的时候, 系统就会通过Mobile手机网络上网。

       这就引出了网络管理的概念, 当有很多网络可用的时候, 系统要决定通过哪个网络联网。 当一个当前突然断开时, 系统要想办法通过其它途径联网。 Android系统中对支持的网络并不是公平对待的, 而是有优先级的, 默认情况下, 系统认为可以通过wifi联网时就绝对不会通过其它途径联网。 我们现在就要看一下这一切表面现象背后的东西。

       目前android 2.3.4 for arm不支持ethernet 但有patch打上即可。 android 2.2 for mips里面有ethernet的支持, android 2.3.4 for mips又拿掉了, 不知道什么原因。

2.       本文目的

       本文主要是要弄清楚两个问题:

l         Android系统是怎样实现对网络的优先级管理的

l         如果要向Android系统中添加新网络的支持, 比如以太网支持, 怎样做才能融合进Android的网络管理系统。

3.       网络管理模块的架构

这里涉及几个重要的类的作用要先介绍一下:

l         ConnectivityManagerAndroid网络状态的API接口, 可通过getSystemService接口获取

l         ConnectivityService:负责Android网络的优先级管理

l         EthernetManager:以太网配置的Android API接口,可通过getSystemService接口获取

l         NetWorkStateTracker 每种网络都有各自NetWorkStateTracker的子类, 来负责以太网状态的监听, ConnectivityService统一管理它们。

l         EthernetService:负责配置信息的保存和读取

l         EthernetStateTracker:继承NetWorkStateTracker 负责以太网状态的监听和配置

下面是Android网络管理的架构图和uml类图:

android <wbr>2.3 <wbr>ethernet

android <wbr>2.3 <wbr>ethernet

      

       EthernetManagerConnectivityManagerAndroid平台提供出来的API,  客户程序可以通过EthernetManager接口配置以太网, 可以通过ConnectivityManager获取网络状态信息。ConnectivityService管理着系统支持的所有网络, 通过每个网络实现的NetWorkStateTracker子类监听网络的状态信息, 系统默认的网络优先级定义在com.android.internal.R.array.radioAttributes 对应的xml内容如下:

   

<!-- An Array of "[Connection name],[ConnectivityManager connection type],

         [associated radio-type],[priority]  -->

    <string-array translatable="false" name="networkAttributes">

        <item>"wifi,1,1,1"</item>

        <item>"mobile,0,0,0"</item>

        <item>"mobile_mms,2,0,2"</item>

        <item>"mobile_supl,3,0,2"</item>

        <item>"mobile_hipri,5,0,3"</item>

        <item>"ethernet,7,7,1"</item>

</string-array>

 

当某个网络有变化时, 它的NetWorkStateTracker子类就会给ConnectivityService发消息,ConnectivityService就会根据优先级大小和网络状态做决策。

4.       情景分析

       架构图和类图并不能给人直观的理解, 我们现在分析几个情景来加深理解。

4.1.      情景一

       假设你的Android系统目前支持MobileEthernet两种网络, Ethernet网络的优先级高于Mobile网络,当前连接上了Mobile网络, 而在Settings里面Ethernet设置为DHCP模式并且为使能状态。 试想如果我们现在连接上网线, 这时情况会如何呢? 由于Ethernet的优先级比Mobile高, 系统就会开始通过Ethernet来联网。

       下图是整个过程的uml序列图:

android <wbr>2.3 <wbr>ethernet

      

       系统启动时EthernetStateTracker就会创建EthernetMonitor线程来监听网络状态信息, 监听的通过jni调用c代码完成的, 原理就是监听NetLink Socket 网络连接或断开时这个socket端口就会接收到信息。当有网线连接上时,EthernetMonitor线程就会给EthernetStateTracker发送EVENT_HW_PHYCONNECT消息,EthernetStateTracker读取配置信息, 由于我们在Settings设置为DHCP, 就会通过DhcpHandleDhcpThread发送EVENT_DHCP_START信息, DhcpThread就会运行NetUtil.runDhcp()来自动获取网络地址。接下来EthernetMonitor线程又会收到网络已通的消息, 并通过EVENT_HW_CONNECTED通知EthernetStateTracker EthernetStateTracker接着会发送EVENT_STATE_CHANGED消息给ConnectivityService, ConnectivityService会比较Ethernet和当前网络(也就是MOBILE)的优先级大小, 做出关闭MOBILE而通过Ethernet来联网的决定。在pc上当切换到其他网络只是disconnected以前的网络, Android为了省电, disable以前网络的。

 

4.2.      情景2

       假设当前系统只支持Ethernet 系统可以静态IP上网, 目前上不了网的原因是Settings里静态IP设置有误, 我们现在进入Settings程序来填写完静态ip点击确定。

       下面是整个点击确定后的uml序列图, 不解释。

android <wbr>2.3 <wbr>ethernet

5.       添加Ethernet支持所需做的添加和改动

l         com.android.content.Context中添加public static final String ETH_SERVICE = "ethernet";

l         改变com.android.app.ContextImplpublic Object getSystemService(String name)方法, 返回EhernetManager EthernetManager只是简单的对IEthernetManager接口的封装, 通过IEthernetManager远程调用到EthernetService

       public Object getSystemService(String name)

       {

              ….……

 

              Else if (ETH_SERVICE.equals(name)) {

            return getEthernetManager();

              }

              ……..

       }

 

       private EthernetManager getEthernetManager()

    {

        synchronized (sSync) {

            if (sEthManager == null) {

                IBinder b = ServiceManager.getService(ETH_SERVICE);

                IEthernetManager service = IEthernetManager.Stub.asInterface(b);

                sEthManager = new EthernetManager(service,                         mMainThread.getHandler());

            }

        }

        return sEthManager;

}

 

l         com.android.server.EthernetService继承IEthernetManager.Stub  IEthernetManager远程调用到的对象, 在构造函数中会根据配置设置以太网状态, 在里面会用android.net.ethernet. EthernetNative接口通过jni调用本地方法, 来获取本地以太网的设备信息。相对的cpp实现在framework/base/core/jni/android_net_ethernet.cpp文件中实现。com.android.server.EthernetService的构造函数有个参数是EthernetStateTracker 它依靠这个tracker监听连接状态来通知ConnectivityService来切换网络。

l         com.android.server. ConnectivityService com.android.os.ServiceManage注册EthernetService 然后调用EthernetStateTracker.startMonitoring()开始监听网络状态;

 

l         com.android.net.ethernet.EthernetStateTracker会调用com.android.net.NetworkUtils中的native方法, 

framework/base/core/jni/android_net_NetUtils.cpp

l         Settings中增加设置以太网参数的界面

 

       总之, 就是要添加一个Manager给应用调用, 添加一个Service来具体完成Manager派发下来的工作,添加一个NetStateTracker并向ConnectivityManager注册来和ConnectivityManager交互。 具体完成网络配置和状态查询的工作在EthernetNativeNetWorkUtils中完成。

6.       NetWorkUtils

    NetWorkUtils里面的接口都是属于协议层, 位于物理层之上, 不管是Ethernet还是Wifi都可以调用NetWorkUtils里面的方法设置静态IP地址, 也可以通过NetWorkUtils来启动通过dhcp获取ip地址。它的接口如下:

public class NetworkUtils {

    public native static int enableInterface(String interfaceName);

    public native static int disableInterface(String interfaceName);

    public native static int addHostRoute(String interfaceName, int hostaddr);

    public native static int setDefaultRoute(String interfaceName, int gwayAddr);

    public native static int getDefaultRoute(String interfaceName);

    public native static int removeHostRoutes(String interfaceName);

    public native static int removeDefaultRoute(String interfaceName);

    public native static int resetConnections(String interfaceName);

    public native static boolean runDhcp(String interfaceName, DhcpInfo ipInfo);

    public native static boolean stopDhcp(String interfaceName);

    public native static boolean releaseDhcpLease(String interfaceName);

    public native static String getDhcpError();

    public static boolean configureInterface(String interfaceName, DhcpInfo ipInfo)

    private native static boolean configureNative(

        String interfaceName, int ipAddress, int netmask, int gateway, int dns1, intdns2);

    public static int lookupHost(String hostname)

}

    NetWorkUtilsjni部分也只是对system/core/libnetutils库的简单封装, libnetutils有时间再深入研究。

   

7.       EthernetNative

       EthernetServiceEthernetStateTracker通过EthernetNative接口访问本地以太网设备相关信息,EthernetNative接口如下, 它的实现在framework/base/core/jni/android_net_ethernet.cpp目录下:

public class EthernetNative {

    public native static String getInterfaceName(int i);

    public native static int getInterfaceCnt();

    public native static int initEthernetNative();

    public native static String waitForEvent();

}

       这里首先推荐看一篇文章http://wenku.baidu.com/view/2fdddefbaef8941ea76e05d8.html

android <wbr>2.3 <wbr>ethernet

       以太网卡名字和数量的信息是通过读取/sys/class/net来获得的, 而网络网线插入和网络状态信息是通过NetLink Socket来监听的。 EthernetService通过NetLink Socket捕捉了4个事件:

l         物理连接(插网线),使能以太网之后插网线才上报

l         物理断开(拔网线),使能以太网之后拔网线才上报

l         网络连接(ip地址配置成功)

l         RM_ADDR(尚不知这是一种什么情况)            

    对于NetLink还没有深入去研究, 有时间要看一下这篇关于NetLink的文章http://qos.ittc.ku.edu/netlink/html/index.html

8.       疑惑

l         当前发现有物理连接时(EVENT_HW_PHYCONNECTED) 就会根据配置调用NetWorkUtils配置ip地址,ip地址配置成功后(EVENT_HW_CONNECTED), 才会向ConnectivityManager通报。是不是先向ConnectivityManager通报, 等批准后再配置ip地址更好一点呢?

      

       目前的理解是: 只有当Ethernet模块确定可以通过自己连接网络才会通知ConnectivityManager 所以先通知ConnectivityManager再配置IP地址是不可行的。

 

l         虽然EthernetNative捕捉了RM_ADDR事件, EthernetMonitor并没有将这个事件通知给EthernetStateTracker 所以ConnectivityManager也就不会知道RM_ADDR事件。现在还不知RM_ADDR触发的条件, 不知不处理会不会产生什么问题。

9.       android 2.3.4 for mips添加以太网支持

l         进入framework/base目录,用git log查看到以前有过添加ethernet支持, 不过后来被revert了, 找到这次revert的版本号, 再次git revertcommit-id”会提示出错, git stagus提示有两个文件冲突, 手动解决下冲突, 顺便改一下framework/base/res/res/values/config中的networkAttributes 把不支持的网络接口去掉。 最后git commit –a –m “readd ethernet support” 

l         android-x86项目的网站下载, 进入package/app/Settings, git am “this patch”时出现冲突,只能git am –abort来终止,然后看patch来手动merge, 最后git commit –a –m “add ethernet support”

l         如果源码还没有编译过, 参照相关文档编译整个源码。  如果源码已经编译过, 为了节省时间, 只需编译改动的。 在顶层目录mmm frameworks/base/; mmm package/app/Settings; 当编译Settings时出错,原因是Frameworkethernet的代码是mips写的, Settings是按x86patch改的, 但不同之处也只是一些函数和常量的名字问题, Settings或改framework都可以解决, 我是改的Settings

l         编译成功后make snod来重新生成镜像, 然后重启emulator可以在Settings里看到如下界面。

android <wbr>2.3 <wbr>ethernet android <wbr>2.3 <wbr>ethernet android <wbr>2.3 <wbr>ethernet

10.   TODO

l         NetLink Socket的原理和用法。

l         libnetutils深入的分析

0 0