Chinaunix首页 | 论坛 | 博客
  • 博客访问: 405396
  • 博文数量: 78
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 940
  • 用 户 组: 普通用户
  • 注册时间: 2013-08-25 09:39
文章分类

全部博文(78)

文章存档

2016年(7)

2015年(1)

2014年(35)

2013年(35)

我的朋友

分类: Android平台

2014-04-19 14:07:31

在Android系统中,不同类型的网络同时开启时,系统根据网络类型的优先级自动进行选择。

1. 网络优先级配置文件

frameworks/base/core/res/res/values/config.xml

与类NetworkConfig的成员变量一一对应,其中,第4个元素就是优先级设置值。

   

        "ethernet,9,9,0,-1,true"

        "wifi,1,1,1,-1,true"

        "mobile,0,0,0,-1,true"

        "mobile_mms,2,0,2,60000,true"

        "mobile_supl,3,0,2,60000,true"

        "mobile_hipri,5,0,3,60000,true"

        "mobile_fota,10,0,2,60000,true"

        "mobile_ims,11,0,2,60000,true"

        "mobile_cbs,12,0,2,60000,true"

        "wifi_p2p,13,1,0,-1,true"

        "pppoe,14,14,1,-1,true"

frameworks/base /core/java/android/net/ConnectivityManager.java中定义了网络类型:

public static final int TYPE_MOBILE      = 0;
public static final int TYPE_WIFI        = 1;

…..

public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI


frameworks/base/packages/SettingsProvider/res/values/defaults.xml

1

SystemServer启动 ConnectivityService服务,用户操作的类是 ConnectivityManager.java 通过aidl访问 ConnectivityService.java提供的服务。

2.ConnectivityService服务

frameworks/base /services/java/com/android/server/ConnectivityService.java

ConnectivityService的构造函数中读取使用网络优先级配置文件。  首先获取config.xml中的字符串保存在String数组naStrings 中,然后循环处理数组中的每个元素(如"wifi,1,1,1,-1,true")。声明一个NetworkConfig对象时把每个String元素作为参数,最后把每个NetworkConfig对象加到数组mNetConfigs中。至此,有关各种网络的配置都保存在数组mNetConfigs里。

网络在启动的时候,会发出一个message(EVENT_STATE_CHANGED),这个消息会在ConnectivityService的内部类NetworkStateTrackerHandler中被处理。

当网络启动时,最终会调用到函数handleConnect。

if (mNetConfigs[newNetType].isDefault()) {

            if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != newNetType) {

                if (isNewNetTypePreferredOverCurrentNetType(newNetType)) {

                    // tear down the other

                    NetworkStateTracker otherNet =

                            mNetTrackers[mActiveDefaultNetwork];

                    if (DBG) {

                        log("Policy requires " + otherNet.getNetworkInfo().getTypeName() + " teardown");

                    }

                    if (!teardown(otherNet)) {

                        loge("Network declined teardown request");

                        teardown(thisNet);

                        return;

                    }

                } else {

                       // don't accept this one

                        if (VDBG) {

                            log("Not broadcasting CONNECT_ACTION " +

                                "to torn down network " + info.getTypeName());

                        }

                        teardown(thisNet);

                        return;

                }

            }

                                                        ......

            mActiveDefaultNetwork = newNetType;

第一个if是判断网络是不是默认路由的,上文提到的config.xml中wifi、Ethernet、mobile都是默认路由的。第二个if是根据变量mActiveDefaultNetwork 来判断是否有其他网络正在运行。如果有的话,就对两种网络的优先级进行比较。优先比较是通过函数isNewNetTypePreferredOverCurrentNetType来实现的。如果返回false则不连接网络并返回。如果返回true则断开当前网络,并把newNetType赋给mActiveDefaultNetwork,确保之后的网络操作使用的是新的网络连接。

         分析函数isNewNetTypePreferredOverCurrentNetType:

private boolean isNewNetTypePreferredOverCurrentNetType(int type) {

        if ((type != mNetworkPreference &&

                    mNetConfigs[mActiveDefaultNetwork].priority >

                    mNetConfigs[type].priority) ||

                mNetworkPreference == mActiveDefaultNetwork) return false;

        return true;

}

((新连接的网络类型 不 等于偏好) 且 (新连接网络类型优先级 低于 当前网络类型优先级)) 

或者 (偏好类型正是当前网络类型))

              则不切 

isNewNetTypePreferredOverCurrentNetType是判断是否切换为新启动的网络。从函数代码可以发现,变量mNetworkPreference 起到了很关键的作用,因为当mActiveDefaultNetwork等于mNetworkPreference时,不管优先级怎样,函数直接返回false。

       通过查找,知道mNetworkPreference是在ConnectivityService的构造函数中初始化的。mNetworkPreference = getPersistedNetworkPreference();

private int getPersistedNetworkPreference() {

        final ContentResolver cr = mContext.getContentResolver();

        final int networkPrefSetting = Settings.Global

                .getInt(cr, Settings.Global.NETWORK_PREFERENCE, -1);

        if (networkPrefSetting != -1) {

            return networkPrefSetting;

        }

        return ConnectivityManager.DEFAULT_NETWORK_PREFERENCE;

    }

 第1、2句是获取ContentProvider与Settings.Global.NETWORK_PREFERENCE对应的值。该ContentProvider是在类DataBaseHelper中初始化,其中有一句关键的代码

db.execSQL("INSERT INTO system ('name', 'value') values ('network_preference', '" +

                        ConnectivityManager.DEFAULT_NETWORK_PREFERENCE + "')");可见其实保存的也是ConnectivityManager.DEFAULT_NETWORK_PREFERENCE的值,故mNetworkPreference = ConnectivityManager.DEFAULT_NETWORK_PREFERENCE。

在ConnectivityService中通过   public NetworkInfo getNetworkInfo(int networkType)方法可以得知当前networkType类型网络的连接情况。

 

阅读(3202) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~