需求
項目中Android 板通過有線連接poe攝像頭肿仑, android app通過wifi跟外部通訊。采用的Android 8.1的代碼神年。
網(wǎng)上搜索發(fā)現(xiàn)有不少實現(xiàn)該功能的文章,不過文章都有一些差異,對于不了解這些模塊的人來說會不知道應該修改哪個考榨。這里只簡單記錄下我的調(diào)試記錄,還沒深究
現(xiàn)象
這邊照著網(wǎng)上幾篇文章修改后鹦倚,出現(xiàn)的現(xiàn)象是:eth0 處于Running的狀態(tài)時河质, 去重連wifi, wifi只會顯示saved震叙,不會繼續(xù)走configure流程
調(diào)試
- 最常見的的方法就是通過打印去了解信息掀鹅,把涉及到NetworkFactory 和ConnectivityService的打印都打開
- 沒有連接eth0時點擊wifi連接的打印
09-03 01:59:40.998 465 561 D WifiStateMachine: connectToUserSelectNetwork netId 3, uid 1000, forceReconnect = false
09-03 01:59:41.033 465 561 D WifiStateMachine: CMD_START_CONNECT sup state DisconnectedState my state DisconnectedState nid=3 roam=false
09-03 01:59:43.300 465 561 D WifiStateMachine: CMD_START_CONNECT sup state ScanState my state DisconnectedState nid=3 roam=false
09-03 01:59:45.650 465 561 E WifiStateMachine: L2ConnectedState enter
- eth0處于running時,點擊wifi連接的打印
09-03 02:02:47.526 465 561 D WifiStateMachine: connectToUserSelectNetwork netId 4, uid 1000, forceReconnect = false
09-03 02:02:47.564 465 561 E WifiStateMachine: CMD_START_CONNECT but no requests and not connected, bailing
由打印的差異 跟蹤到代碼
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java
case CMD_START_CONNECT:
/* connect command coming from auto-join */
netId = message.arg1;
int uid = message.arg2;
bssid = (String) message.obj;
synchronized (mWifiReqCountLock) {
if (!hasConnectionRequests()) {
loge("hasConnectionRequests :......");
if (mNetworkAgent == null) {
loge("CMD_START_CONNECT but no requests and not connected,"
+ " bailing");
break;
} else if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) {
loge("CMD_START_CONNECT but no requests and connected, but app "
+ "does not have sufficient permissions, bailing");
break;
}
}
}
config = mWifiConfigManager.getConfiguredNetworkWithPassword(netId);
logd("CMD_START_CONNECT sup state "
+ mSupplicantStateTracker.getSupplicantStateName()
+ " my state " + getCurrentState().getName()
+ " nid=" + Integer.toString(netId)
+ " roam=" + Boolean.toString(mIsAutoRoaming));
if (config == null) {
loge("CMD_START_CONNECT and no config, bail out...");
break;
}
private boolean hasConnectionRequests() {
return mConnectionReqCount > 0 || mUntrustedReqCount > 0;
}
從打印和代碼分析媒楼,兩個流程的差異主要在hasConnectionRequests這個函數(shù)
- 接下來主要跟蹤hasConnectionRequests
從代碼查到主要問題在mConnectionReqCount這個變量乐尊,所以查找修改這個變量的地方,還好只有兩處:
@Override
protected void needNetworkFor(NetworkRequest networkRequest, int score) {
synchronized (mWifiReqCountLock) {
loge("needNetworkFor mConnectionReqCount="+ mConnectionReqCount);
if (++mConnectionReqCount == 1) {
if (mWifiConnectivityManager != null && mUntrustedReqCount == 0) {
mWifiConnectivityManager.enable(true);
}
}
}
}
@Override
protected void releaseNetworkFor(NetworkRequest networkRequest) {
synchronized (mWifiReqCountLock) {
loge("releaseNetworkFor mConnectionReqCount="+ mConnectionReqCount);
Exception e = new Exception("log");
e.fillInStackTrace();
loge("Called: " , e);
if (--mConnectionReqCount == 0) {
if (mWifiConnectivityManager != null && mUntrustedReqCount == 0) {
mWifiConnectivityManager.enable(false);
}
}
}
}
為了能知道對這個變量的調(diào)用流程划址,一個簡單的方法就是利用Exception打印出堆棧信息
Exception e = new Exception("log");
e.fillInStackTrace();
loge("Called: " , e);
- 堆棧打印信息忘記記下來了扔嵌,這里只記下最后修改的地方
frameworks/base/core/java/android/net/NetworkFactory.java
private void evalRequest(NetworkRequestInfo n) {
if (VDBG) log("evalRequest");
Log.e("NetworkFactory", "evalRequest n.score:" + n.score + ", mScore:" + mScore);
if (n.requested == false && n.score < mScore &&
n.request.networkCapabilities.satisfiedByNetworkCapabilities(
mCapabilityFilter) && acceptRequest(n.request, n.score)) {
if (VDBG) log(" needNetworkFor");
needNetworkFor(n.request, n.score);
n.requested = true;
} else if (n.requested == true &&
(n.score > mScore || n.request.networkCapabilities.satisfiedByNetworkCapabilities(
mCapabilityFilter) == false || acceptRequest(n.request, n.score) == false)) {
if (VDBG) log(" releaseNetworkFor");
releaseNetworkFor(n.request);
n.requested = false;
} else {
if (VDBG) log(" done");
}
}
將下面兩行注釋掉
//releaseNetworkFor(n.request);
//n.requested = false;
最終修改的地方有3處:
- 寫一個啟動腳本,在系統(tǒng)啟動時配置eth0, ip地址與wifi不在同一個網(wǎng)斷
ip route add 192.168.11.0/24 dev eth0 proto static table local_network
ip route flush cache
sleep 5s
ifconfig eth0 192.168.11.120
- 修改frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetNetworkFactory.java
private static final int NETWORK_SCORE = 30; //70;
- 修改frameworks/base/core/java/android/net/NetworkFactory.java
注釋掉
//releaseNetworkFor(n.request);
//n.requested = false;