专栏首页构建FFmpeg Android播放器rk3399 wifi和eth0共存 调试

rk3399 wifi和eth0共存 调试

需求

项目中Android 板通过有线连接poe摄像头, android app通过wifi跟外部通讯。采用的Android 8.1的代码。

网上搜索发现有不少实现该功能的文章,不过文章都有一些差异,对于不了解这些模块的人来说会不知道应该修改哪个。这里只简单记录下我的调试记录,还没深究

现象

这边照着网上几篇文章修改后,出现的现象是:eth0 处于Running的状态时, 去重连wifi, wifi只会显示saved,不会继续走configure流程

调试

  1. 最常见的的方法就是通过打印去了解信息,把涉及到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这个函数

  1. 接下来主要跟踪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);
                    }
                }
            }
        }

为了能知道对这个变量的调用流程,一个简单的方法就是利用Exception打印出堆栈信息 Exception e = new Exception("log"); e.fillInStackTrace(); loge("Called: " , e);

  1. 堆栈打印信息忘记记下来了,这里只记下最后修改的地方 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处:

  1. 写一个启动脚本,在系统启动时配置eth0, ip地址与wifi不在同一个网断
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
  1. 修改frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetNetworkFactory.java
private static final int NETWORK_SCORE = 30; //70;
  1. 修改frameworks/base/core/java/android/net/NetworkFactory.java 注释掉
  //releaseNetworkFor(n.request);
  //n.requested = false;

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • MediaPlayer(九)--reset()流程

    frameworks/base/media/java/android/media/MediaPlayer.java

    小蚂蚁与大象
  • MeidaPlayer(六)--setDisplay流程

    在Activity 的OnSurfaceCreate回调后,表示Surface已经创建成功,可以将surface传到native层player

    小蚂蚁与大象
  • MediaPlayer(十)--release()流程

    小蚂蚁与大象
  • 复杂Excel转换与导入

      把不同客户提供Excel 直接导入到系统中生成对应的收货单或是出货单。后端创建收货端和出货单的接口已经有现成的webservice或是标准的xml;这类需要...

    阿新
  • python基本数据类型的介绍

    在32位机器上,整数的位数为32位,取值范围为-2**31~2**31-1,即-2147483648~2147483647

    py3study
  • Qt代码风格

    Qt君
  • Qt编写数据可视化大屏界面电子看板10-改造QCustomPlot

    为了抛弃对QChart的依赖,以及echart的依赖,(当然,后期也会做qchart的版本和echart的版本,尤其是echart的版本是肯定会做的,毕竟ech...

    feiyangqingyun
  • 从HashMap到ConcurrentHashMap

    《HashMap》中已经分析了HashMap的实现,jdk1.7与jdk1.8的实现有很多区别,现在我们分析一下两个版本的差异:

    搬砖俱乐部
  • LinkedHashMap和LruCache源码分析

    LinkedHashMap是HashMap的子类,与HashMap有着同样的存储结构,但它加入了一个双向链表的头结点,将所有put到LinkedHashMap的...

    曾大稳
  • js函数解读

    东风冷雪

扫码关注云+社区

领取腾讯云代金券