首页 > 系统 > Android > 正文

Android网络优先级及更改

2019-11-08 00:26:35
字体:
来源:转载
供稿:网友

from:http://blog.csdn.net/u013686019/article/details/51447129

Android版本:

[java] view plain copy PRint?在CODE上查看代码片Android 4.4.4  涉及内容:[html]%20view%20plain%20copy%20print?1,网络优先级;  2,网络切换;  3,界面显示。  解决问题:[html]%20view%20plain%20copy%20print?1,更改网络优先级:让以太网(eth0)优先级高于WiFi(Wlan0);  2,WiFi切换到以太网异常原因及解决。  一、网络优先级1、Android支持的网络类型Android系统framework层的ConnectivityManager.java文件中定义了支持的所有网络类型:[java]%20view%20plain%20copy%20print?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 TYPE_MOBILE_MMS  = 2;  public static final int TYPE_MOBILE_SUPL = 3;  public static final int TYPE_MOBILE_DUN  = 4;  public static final int TYPE_MOBILE_HipRI = 5;  public static final int TYPE_WIMAX       = 6;  public static final int TYPE_BLUETOOTH   = 7;  public static final int TYPE_DUMMY       = 8;  public static final int TYPE_ETHERNET    = 9;  public static final int TYPE_MOBILE_FOTA = 10;  public static final int TYPE_MOBILE_IMS  = 11;  public static final int TYPE_MOBILE_CBS  = 12;  public static final int TYPE_WIFI_P2P    = 13;  对于上网,接触的几乎都是TYPE_WIFI、TYPE_MOBILE、TYPE_ETHERNET这三种。这些网络的优先级定义在config.xml文件的networkAttributes数组中:[html]%20view%20plain%20copy%20print?frameworks/base/core/res/res/values/config.xml  <!-- This string array should be overridden by the device to present a list of network attributes, based on the hardware -->  <string-array translatable="false" name="networkAttributes">      <item>"wifi,1,1,1,-1,true"</item>        <item>"mobile,0,0,0,-1,true"</item>      <item>"mobile_mms,2,0,2,60000,true"</item>      <item>"mobile_supl,3,0,2,60000,true"</item>      <item>"mobile_hipri,5,0,3,60000,true"</item>      <item>"mobile_fota,10,0,2,60000,true"</item>      <item>"mobile_ims,11,0,2,60000,true"</item>      <item>"mobile_cbs,12,0,2,60000,true"</item>      <item>"wifi_p2p,13,1,0,-1,true"</item>      <item>"mobile_ia,14,0,2,-1,true"</item>      <item>"bluetooth,7,7,1,60000,true"</item>      <item>"eth,9,9,4,60000,true"</item>  </string-array>  注意networkAttributes数组前的注释!大意是说,对某种网络支持与否取决与硬件,所以该文件会被源码目录/device/下的config.xml定义的networkAttributes数组覆盖!!!也就是说,真正起作用的优先级配置在源码目录/device/下的config.xml中定义。对于networkAttributes数组的每一个item:[html]%20view%20plain%20copy%20print?<item>"wifi,1,1,1,-1,true"</item>  其含义由NetworkConfig.java描述(一一对应):[html]%20view%20plain%20copy%20print?frameworks/base/core/java/android/net/NetworkConfig.java  public class NetworkConfig {      /**       * Human readable string       */      public String name;      /**       * Type from ConnectivityManager       */      public int type;      /**       * the radio number from radio attributes config       */      public int radio;      /**       * higher number == higher priority when turning off connections       */      public int priority;      /**       * indicates the boot time dependencyMet setting       */      public boolean dependencyMet;      /**       * indicates the default restoral timer in seconds       * if the network is used as a special network feature       * -1 indicates no restoration of default       */      public int restoreTime;      /**       * input string from config.xml resource.  Uses the form:       * [Connection name],[ConnectivityManager connection type],       * [associated radio-type],[priority],[dependencyMet]       */      public NetworkConfig(String init) {          String fragments[] = init.split(",");          name = fragments[0].trim().toLowerCase(Locale.ROOT);          type = Integer.parseInt(fragments[1]);          radio = Integer.parseInt(fragments[2]);          priority = Integer.parseInt(fragments[3]);          restoreTime = Integer.parseInt(fragments[4]);          dependencyMet = Boolean.parseBoolean(fragments[5]);      }  }  2、更改以太网优先级高于WiFi[html]%20view%20plain%20copy%20print?<item>"eth,9,9,0,60000,true"</item>  并设置Preferred网络为以太网:[html]%20view%20plain%20copy%20print?frameworks/base/services/java/com/android/server/ConnectivityService.java  mNetworkPreference = getPersistedNetworkPreference();  private int getPersistedNetworkPreference() {      final ContentResolver cr = mContext.getContentResolver();      // 设置Preferred网络为TYPE_ETHERNET      Settings.Global.putInt(cr, Settings.Global.NETWORK_PREFERENCE, ConnectivityManager.TYPE_ETHERNET);      final int networkPrefSetting = Settings.Global              .getInt(cr, Settings.Global.NETWORK_PREFERENCE, -1);      log("networkPrefSetting: " + networkPrefSetting);      if (networkPrefSetting != -1) {          return networkPrefSetting;      }      return ConnectivityManager.DEFAULT_NETWORK_PREFERENCE;  }  3、网络优先级的读取[html]%20view%20plain%20copy%20print?frameworks/base/services/java/com/android/server/ConnectivityService.java  public ConnectivityService() {      if (DBG) log("ConnectivityService starting up");      boolean wifiOnly = SystemProperties.getBoolean("ro.radio.noril", false);      log("wifiOnly=" + wifiOnly);      String[] naStrings = context.getResources().getStringArray(com.android.internal.R.array.networkAttributes);      for (String naString : naStrings) {          try {              NetworkConfig n = new NetworkConfig(naString);              if (VDBG) log("naString=" + naString + " config=" + n);                            mNetConfigs[n.type] = n;              mNetworksDefined++;          }      }  }  Log如下:

二、网络切换现在,优先级:Ethernet > WiFi,在WiFi连接的情况下,点击【使用以太网】按钮进行网络切换:先响应一个EVENT_CONFIGURATION_CHANGED事件:[html] view plain copy print?在CODE上查看代码片frameworks/base/services/java/com/android/server/ConnectivityService.java  case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED: {      info = (NetworkInfo) msg.obj;      handleConnectivityChange(info.getType(), false);      break;  }  对网络是否切换的仲裁在handleConnect()方法中调用的isNewNetTypePreferredOverCurrentNetType()方法:[html]%20view%20plain%20copy%20print?frameworks/base/services/java/com/android/server/ConnectivityService.java  private void handleConnect(NetworkInfo info) {      final int newNetType = info.getType();      if (VDBG) {          log("handleConnect: E newNetType=" + newNetType + " thisIface=" + thisIface                  + " isFailover" + isFailover);      }      // if this is a default net and other default is running      // kill the one not preferred      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;              }          }      }  }  private boolean isNewNetTypePreferredOverCurrentNetType(int type) {      log("type = "+ type);      log("mNetworkPreference = " + mNetworkPreference);      log("mActiveDefaultNetwork = " + mActiveDefaultNetwork);      log("mNetConfigs[mActiveDefaultNetwork].priority = " + mNetConfigs[mActiveDefaultNetwork].priority);      log("mNetConfigs[type].priority = " + mNetConfigs[type].priority);      if (((type != mNetworkPreference)                    && (mNetConfigs[mActiveDefaultNetwork].priority > mNetConfigs[type].priority))                 || (mNetworkPreference == mActiveDefaultNetwork)) {          log("return false");          return false;      }      log("return true");      return true;  }  mNetworkPreference%20=%209,之前设置的Preferred网络。mActiveDefaultNetwork%20=%201,当前使用的网络,即WiFi。经过isNewNetTypePreferredOverCurrentNetType()的仲裁,返回true进行网络切换:[html]%20view%20plain%20copy%20print?Policy requires WIFI teardown  至此,Ethernet当道,WiFi让行。三、界面显示在【Settings-->以太网】界面,【使用以太网】选项一直处于连接状态且不可点击,IP地址等信息亦不见;此时进入Shell用ifconfig查看IP,可知以太网IP等已经获取、且WiFi已经断掉、且ping网络正常。原因去在Settings部分查找:[java] view plain copy print?在CODE上查看代码片packages/apps/settings/src/com/android/settings/ethernet/EthernetSettings.java  public void getEthInfo(int state){        if (state == EthernetDataTracker.ETHER_STATE_CONNECTING) {              mUseEthernet.setEnabled(false);          mUseEthernet.setSummary(R.string.ethernet_connecting);              clearIpInfo();      } else if (state == EthernetDataTracker.ETHER_STATE_DISCONNECTED) {              mUseEthernet.setEnabled(true);          mUseEthernet.setSummary(R.string.ethernet_unconnected);              clearIpInfo();      } else if (state == EthernetDataTracker.ETHER_STATE_CONNECTED) {          mUseEthernet.setEnabled(true);          mUseEthernet.setSummary(R.string.ethernet_connected);                    if(isUsingStaticIp()) {              getEthInfoFromStaticIP();          } else {              getEthInfoFromDhcp();          }          mEthmac = getEthMac();      }  }  mUseEthernet不可用原因是以太网一直处于ETHER_STATE_CONNECTING状态,以太网状态来自:[java]%20view%20plain%20copy%20print?packages/apps/settings/src/com/android/settings/ethernet/EthernetSettings.java  private final BroadcastReceiver mReceiver = new BroadcastReceiver() {      @Override      public void onReceive(Context context, Intent intent) {          int state = intent.getIntExtra(EthernetDataTracker.EXTRA_ETHERNET_STATE, 0);          Log.d(TAG, "BroadcastReceiver: Ethernet current state:" + state);          getEthInfo(state);      }  };  广播发送地:[java]%20view%20plain%20copy%20print?frameworks/base/core/java/android/net/EthernetDataTracker.java  private void runDhcp() {      Log.d(TAG, "mIface = " + mIface + ", isEthernetEnabled() = " + isEthernetEnabled());      if(!mIface.isEmpty() && isEthernetEnabled()) {          registerEthernetContentObserver(); // register here when boot with plugged ethernet          {              // send connected msg only when wifi disconnect              if(!IsWiFiConnected()) {                  sendEthStateChangedBroadcast(ETHER_STATE_CONNECTED);              } else {                  Log.e(TAG, "WiFiConnected, cannot send ETHER_STATE_CONNECTED MSG");              }          }      }  }  private Boolean IsWiFiConnected() {      try {          ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);          boolean isWiFiConnected = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected();          Log.e(TAG, "isWiFiConnected: " + isWiFiConnected);          return isWiFiConnected;      }  }  可知:虽然WiFi已经被teardown,但IsWiFiConnected()依旧返回true,即WiFi状态没被更新:[java]%20view%20plain%20copy%20print?派生到我的代码片frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java  public boolean teardown() {      mTeardownRequested.set(true);      mWifiManager.stopWifi();      return true;  }  IsWiFiConnected()运行先于WiFi的teardown(),所以在teardown()更改WiFi的状态是无效的。。。既然现在需要Ethernet优先级高于WiFi,直接让IsWiFiConnected()返回false即可。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表