Android4.4以太网移植问题

  最近在android4.4上边移植以太网遇到一个问题,手动设置ip的时候dns无法保存,平台telechip tcc8935

相关的代码目录:

v14.04_r1_tcc-android-4.4.2/frameworks/base/services/java/com/android/server/ConnectivityService.java

v14.04_r1_tcc-android-4.4.2/frameworks/base/services/java/com/android/server/EthernetService.java

v14.04_r1_tcc-android-4.4.2/frameworks/base/core/java/android/net/ConnectivityManager.java

1. 网络优先级配置文件

v14.04_r1_tcc-android-4.4.2/device/telechips/m805_893x/overlay/frameworks/base/core/res/res/values/config.xml

各种不同类型的网络是在文件config.xml中进行配置,config.xml的路径如下:\android\frameworks\base\core\res\res\values 其中网络配置的内容如下:

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

02.<item>"wifi,1,1,1,-1,true"</item>

03.<item>"ethernet,9,9,0,-1,true"</item>

04.<item>"mobile,0,0,0,-1,true"</item>

05.<item>"mobile_mms,2,0,2,60000,true"</item>

06.<item>"mobile_supl,3,0,2,60000,true"</item>

07.<item>"mobile_hipri,5,0,3,60000,true"</item>

08.<item>"mobile_fota,10,0,2,60000,true"</item>

09.<item>"mobile_ims,11,0,2,60000,true"</item>

10.<item>"mobile_cbs,12,0,2,60000,true"</item>

11.<item>"wifi_p2p,13,1,0,-1,true"</item>

12.</string-array>

上面各项字符串的排列顺序与类NetworkConfig的成员变量一一对应,按顺序如下:

name,type,radio,priority,restoreTime,dependencyMet

第4个元素就是我们需要的优先级设置值

2. ConnectivityService服务

在上面的内容中,我们在配置文件中设置了不同网络类型的优先级。那么配置文件里面的设置是在什么时候被系统读取使用的呢?通过查看源代码会发现是在类ConnectivityService的构造函数中被调用的。具体代码如下:

view sourceprint?

01.String[] naStrings = context.getResources().getStringArray(

02.com.android.internal.R.array.networkAttributes);

03.for (String naString : naStrings) {

04.try {

05.NetworkConfig n = new NetworkConfig(naString);

06.if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) {

07.loge("Error in networkAttributes - ignoring attempt to define type " +

08.n.type);

09.continue;

10.}

11.if (mNetConfigs[n.type] != null) {

12.loge("Error in networkAttributes - ignoring attempt to redefine type " +

13.n.type);

14.continue;

15.}

16.if ((mRadioAttributes[n.radio] == null) && (n.type != ConnectivityManager.TYPE_ETHERNET)) {

17.loge("Error in networkAttributes - ignoring attempt to use undefined " +

18."radio " + n.radio + " in network type " + n.type);

19.continue;

20.}

21.mNetConfigs[n.type] = n;

22.mNetworksDefined++;

23.catch(Exception e) {

24.// ignore it - leave the entry null

25.}

26.}

首先获取config.xml中的字符串保存在String数组naStrings 中,然后循环处理数组中的每个元素(如"wifi,1,1,1,-1,true")。之前我们说过,每个元素中的各项跟类NetworkConfig的成员变量对应。这里的处理主要是在声明一个NetworkConfig对象时把每个String元素作为参数,最后把每个NetworkConfig对象加到数组mNetConfigs中。至此,有关各种网络的配置都保存在数组mNetConfigs里。接下来,看看mNetConfigs数组是在什么时候派上用场的?

通过阅读源代码,可以知道各种网络在启动的时候,会发出一个message(EVENT_STATE_CHANGED),这个消息会在ConnectivityService的内部类NetworkStateTrackerHandler中被处理。代码如下:

view sourceprint?

01.private class NetworkStateTrackerHandler extends Handler {

02.......

03.@Override

04.public void handleMessage(Message msg) {

05.NetworkInfo info;

06.switch (msg.what) {

07.case NetworkStateTracker.EVENT_STATE_CHANGED:

08.......

09.if (info.getDetailedState() ==

10.NetworkInfo.DetailedState.FAILED) {

11.handleConnectionFailure(info);

12.else if (info.getDetailedState() ==

13.DetailedState.CAPTIVE_PORTAL_CHECK) {

14.handleCaptivePortalTrackerCheck(info);

15.else if (state == NetworkInfo.State.DISCONNECTED) {

16.handleDisconnect(info);

17.else if (state == NetworkInfo.State.SUSPENDED) {

18.handleDisconnect(info);

19.else if (state == NetworkInfo.State.CONNECTED) {

20.handleConnect(info);

21.}

22.......

当网络启动时,最终会调用到函数handleConnect,下面看看handleConnect具体实现:

view sourceprint?

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

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

03.if (isNewNetTypePreferredOverCurrentNetType(newNetType)) {

04.// tear down the other

05.NetworkStateTracker otherNet =

06.mNetTrackers[mActiveDefaultNetwork];

07.if (DBG) {

08.log("Policy requires " + otherNet.getNetworkInfo().getTypeName() +

09." teardown");

10.}

11.if (!teardown(otherNet)) {

12.loge("Network declined teardown request");

13.teardown(thisNet);

14.return;

15.}

16.else {

17.// don't accept this one

18.if (VDBG) {

19.log("Not broadcasting CONNECT_ACTION " +

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

21.}

22.teardown(thisNet);

23.return;

24.}

25.}

26.......

27.mActiveDefaultNetwork = newNetType;

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

到这里已经完成了网络切换的流程。下面分析函数isNewNetTypePreferredOverCurrentNetType,代码如下:

view sourceprint?

1.private boolean isNewNetTypePreferredOverCurrentNetType(int type) {

2.if ((type != mNetworkPreference &&

3.mNetConfigs[mActiveDefaultNetwork].priority >

4.mNetConfigs[type].priority) ||

5.mNetworkPreference == mActiveDefaultNetwork) return false;

6.return true;

7.}

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

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

mNetworkPreference = getPersistedNetworkPreference();

下面看一下函数getPersistedNetworkPreference返回的是什么值?

.private int getPersistedNetworkPreference() {

02.final ContentResolver cr = mContext.getContentResolver();

03. 

04.final int networkPrefSetting = Settings.Global

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

06.if (networkPrefSetting != -1) {

07.return networkPrefSetting;

08.}

09. 

10.return ConnectivityManager.DEFAULT_NETWORK_PREFERENCE;

11.}

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

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

2.ConnectivityManager.DEFAULT_NETWORK_PREFERENCE + "')");

可见其实保存的也是ConnectivityManager.DEFAULT_NETWORK_PREFERENCE的值。至此,可以明确一点,那就是

mNetworkPreference = ConnectivityManager.DEFAULT_NETWORK_PREFERENCE

3 网络相关的svc命令

上面我们提到的变量mNetworkPreference除了在初始化的时候会改变它的值,还有一个函数也能改变它的值。这个函数是ConnectivityService中的setNetworkPreference。查看源代码可以发现,DataCommand和WifiCommand都调用了ConnectivityService中的这个函数。而DataCommand和WifiCommand是在Svc中初始化的。看到这里,大概可以猜到通过Android的svc命令能够实现上述两个类定义的功能。其中,DataCommand实现对移动网络的开启、关闭和优先选择设置,WifiCommand实现对wifi网络的开启、关闭和优先选择设置。下面看一下命令svc的使用方法:

01.# svc data

02.svc data

03.Control mobile data connectivity

04.usage: svc data [enable|disable]

05.Turn mobile data on or off.

06.//设置移动网络的数据是否启用

07.svc data prefer

08.Set mobile as the preferred data network

09.//设置移动网络的数据优先于WIFI

10. 

11.# svc wifi

12.svc wifi

13.Control the Wi-Fi manager

14.usage: svc wifi [enable|disable]

15.Turn Wi-Fi on or off.//设置WIFI是否启用

16.svc wifi prefer

17.Set Wi-Fi as the preferred data network //设置WIFI优先于移动网络的数据,一般应设置成这样,除非你刻意使用移动网络数据传输

svc data prefer最终会改变mNetworkPreference的值。


//以上为优先级文件

//静态获取ip

以太网文件

v14.04_r1_tcc-android-4.4.2/frameworks/base/ethernet/java/android/net/ethernet/EthernetStateTracker.java

在EthernetStateTracker.java的private boolean configureInterface(EthernetDevInfo info) throws UnknownHostException {中

if (info.getConnectMode().equals(EthernetDevInfo.ETH_CONN_MODE_DHCP)) {//动态获取ip地址

                        if(LOCAL_LOG) Log.i(TAG, "trigger dhcp for device " + info.getIfName());

                        mDhcpTarget.sendEmptyMessage(EVENT_DHCP_START);

                } else {//手动获取ip地址

                        int event;

                        mStartingDhcp = false;


                        mDhcpInfo.ipAddress = stringToIpAddr(info.getIpAddress());

                        mDhcpInfo.gateway = stringToIpAddr(info.getRouteAddr());

                        //mDhcpInfo.netmask = stringToIpAddr(info.getNetMask());

                        mDhcpInfo.netmask = NetworkUtils.netmaskIntToPrefixLength(stringToIpAddr(info.getNetMask()));

                        mDhcpInfo.dns1 = stringToIpAddr(info.getDnsAddr());

                        mDhcpInfo.dns2 = 0;


                        if(LOCAL_LOG) Log.i(TAG, "set ip manually " + mDhcpInfo.toString();


public void notifyStateChange(String ifname,DetailedState state) {//状态改变的函数,更新网络状态











你可能感兴趣的:(android,ethernet)