最近在在5.1移植了以太网过来,移植的过程并没有什么大问题,修改了框架上的代以及添加了Settings代码,以太网调试就基本完工了,后面只是修改下布局即可。但是网络切换策略就有所变化了,就不得不重新认识5.1的网络切换策略了。
在android4.4上,想实现以太网为优先级最高(意思是以太网打开了,WIFI就无法打开),方法很简单,只需要在default.xml和ConnectivityServicet修改就好了。但在5.1系统上就做了新的调整,具体改动的原因不明,他是依靠网络评分的大小 来确定谁的优先级高,废话不多说,以以太网为例子,进行追踪。
1、frameworks\opt\net\ethernet\java\com\android\server\ethernet\EthernetServiceImpl
public EthernetServiceImpl(Context context) {
mContext = context;
Log . i(TAG , "Creating EthernetConfigStore" );
mEthernetConfigStore = new EthernetConfigStore();
mIpConfiguration = mEthernetConfigStore. readIpAndProxyConfigurations();
Log . i(TAG , "Read stored IP configuration: " + mIpConfiguration);
mTracker = new EthernetNetworkFactory(mListeners);
mTracker. setContext(context);
}
2、frameworks\opt\net\ethernet\java\com\android\server\ethernet\EthernetNetworkFactory
EthernetNetworkFactory(RemoteCallbackList<IEthernetServiceListener> listeners) {
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0 , NETWORK_TYPE, "" );
mLinkProperties = new LinkProperties();
initNetworkCapabilities();
mListeners = listeners;
}
public synchronized void start (Context context, Handler target) {
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
mNMService = INetworkManagementService.Stub.asInterface(b);
mEthernetManager = (EthernetManager) context.getSystemService(Context.ETHERNET_SERVICE);
mIfaceMatch = context.getResources().getString(
com.android.internal.R.string.config_ethernet_iface_regex);
mFactory = new LocalNetworkFactory(NETWORK_TYPE, context, target.getLooper());
mFactory.setCapabilityFilter(mNetworkCapabilities);
**mFactory.setScoreFilter(-1 );**
mFactory.register();
private void updateInterfaceState (String iface, boolean up) {
if (!mIface.equals(iface)) {
return ;
}
Log.d(TAG, "updateInterface: " + iface + " link " + (up ? "up" : "down" ));
synchronized (this ) {
mLinkUp = up;
mNetworkInfo.setIsAvailable(up);
if (!up) {
mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null , mHwAddr);
sendEthernetStateChangedBroadcast(EthernetManager.ETHER_STATE_DISCONNECTED);
}
updateAgent();
mFactory.setScoreFilter(up ? NETWORK_SCORE : -1 );
}
}
public void updateAgent () {
synchronized (EthernetNetworkFactory.this ) {
if (mNetworkAgent == null ) return ;
if (DBG) {
Log.i(TAG, "Updating mNetworkAgent with: " +
mNetworkCapabilities + ", " +
mNetworkInfo + ", " +
mLinkProperties);
}
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
mNetworkAgent.sendNetworkInfo(mNetworkInfo);
mNetworkAgent.sendLinkProperties(mLinkProperties);
mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : 0 );
}
}
3、在深入去看看sendNetworkScore(score)到底做了写什么。
public void sendNetworkScore (int score) {
if (score < 0 ) {
throw new IllegalArgumentException("Score must be >= 0" );
}
queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new Integer(score));
}
4、全局搜索了下,发现这个消息在ConnectivityService处理了。
case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: {
NetworkAgentInfo nai = mNetworkAgentInfos.get (msg.replyTo);
if (nai == null ) {
loge("EVENT_NETWORK_SCORE_CHANGED from unknown NetworkAgent" );
break ;
}
Integer score = (Integer) msg.obj;
if (score != null ) updateNetworkScore(nai, score.intValue());
break ;
}
private void updateNetworkScore (NetworkAgentInfo nai, int score) {
if (DBG) log("updateNetworkScore for " + nai.name() + " to " + score);
if (score < 0 ) {
loge("updateNetworkScore for " + nai.name() + " got a negative score (" + score +
"). Bumping score to min of 0" );
score = 0 ;
}
final int oldScore = nai.getCurrentScore();
nai.setCurrentScore(score);
rematchAllNetworksAndRequests(nai, oldScore);
sendUpdatedScoreToFactories(nai);
}
4、getCurrentScore();
private int getCurrentScore(boolean pretendValidated) {
int score = currentScore;
if (networkCapabilities. hasTransport(NetworkCapabilities. TRANSPORT_EPDG)) {
Log . d(TAG ,"[peng add] Support for EPDG testing,this score --->" + score);
return score;
}
if (networkCapabilities. hasTransport(NetworkCapabilities. TRANSPORT_ETHERNET)) {
Log . d(TAG ,"[peng add] Support for TRANSPORT_ETHERNET ,this score --->" + score);
return score;
}
if (! everValidated && ! pretendValidated){
score -= UNVALIDATED_SCORE_PENALTY;
Log . d(TAG ,"[peng add] everValidated and pretendValidated is false,this score --->" + score);
}
if (score < 0 ) score = 0 ;
if (networkMisc. explicitlySelected){
score = EXPLICITLY_SELECTED_NETWORK_SCORE;
Log . d(TAG ,"[peng add] networkMisc.explicitlySelected,this score full--->" + score);
}
return score;
}
5、网络切换,主要看ConnectivityService的rematchNetworkAndRequests方法。
…………
if (VDBG) {
log("currentScore = " +
(currentNetwork != null ? currentNetwork.getCurrentScore () : 0 ) +
", newScore = " + newNetwork.getCurrentScore ())
}
if (currentNetwork == null ||
currentNetwork.getCurrentScore () <= newNetwork.getCurrentScore ()) { //当连接的网络评分小于或等于新的连接网络评分,那么就remove当前网络,连接新的网络。 也就可以分析出,只要是后者连的,优先级就最高。
if (currentNetwork != null) {
if (DBG) log(" accepting network in place of " + currentNetwork.name ())
currentNetwork.networkRequests .remove (nri.request .requestId )
currentNetwork.networkLingered .add (nri.request )
affectedNetworks.add (currentNetwork)
} else {
if (DBG) log(" accepting network in place of null" )
}
…………
6、如何设置以太网优先级最高?
将EthernetNetworkFactory的以太网评分增加
private static final int NETWORK_SCORE = 110; //大于100即可,因为WIFI最大的评分是100
在NetworkAgentInfo的getCurrentScore方法里添加以太网的评分,保证不被修改
//add by peng , set ethernet priority highest.
if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
Log.d(TAG,"[peng add] Support for TRANSPORT_ETHERNET ,this score --->"+score);
return score;
}
“`
这样就可以避免WIFI和以太网同时连接了。具体问题具体分析,以上是个人观点,如果解释的不对,请多多包含。