Android10.0(Q) MTK平台增加以太网静态IP功能

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Android10.0(Q) MTK平台增加以太网静态IP功能

前言


朋友们,网卡功能真的是太太太太常用了,这次我又带着 10.0 的以太网静态IP功能来了,相比 9.0 而言,


framework 没啥大变化,可以直接对比移植。Settings 部分也没啥大变化,preference 对应的包由 v7


变成 androidx,这个导报的时候注意下就行。


效果图


效果图就不贴了,和 9.0 一样都是横屏,差别不大。


上代码


app层


Settins 源码和9.0无差别,完整代码资源链接


这里列下差异地方。

vendor\mediatek\proprietary\packages\apps\MtkSettings\src\com\android\settings\ethernet\EthernetStaticIP.java

9.0 导包

import android.support.v7.preference.Preference;
import android.preference.PreferenceActivity;
import android.support.v7.preference.PreferenceScreen;
import android.support.v7.preference.CheckBoxPreference;
import android.support.v7.preference.EditTextPreference;
import android.support.v14.preference.SwitchPreference;


10.0 导包


import androidx.preference.Preference;
import android.preference.PreferenceActivity;
import androidx.preference.PreferenceScreen;
import androidx.preference.CheckBoxPreference;
import androidx.preference.EditTextPreference;
import androidx.preference.SwitchPreference;

framework 层


修改文件清单

 alps/frameworks/base/api/current.txt                                                                              
 alps/frameworks/base/core/java/android/provider/Settings.java                                                      
 alps/frameworks/base/proto/src/metrics_constants/metrics_constants.proto                                           
 alps/frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetServiceImpl.java                        
 alps/frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetTracker.java


完整代码资源链接


几个注意点


Settings.java 新增字段编译


10.0 之前通过执行命令 make update-api,将新增字段保存到 frameworks/base/api/current.txt 文件中,


这样 java 类引用编译时不报错。10.0 编译命令修改为 make api-stubs-docs-update-current-api


不插网线设置静态IP保存后显示网卡图标bug


不知道你的版本是否也存在这样的bug,不插网线的情况下,设置完静态 ip 各项参数保存后

你惊奇发现状态栏网卡图标出来了。来看下问题日志

2020-05-29 10:07:59.537 1078-1416/system_process D/MtkConnectivityService: registerNetworkAgent NetworkAgentInfo{ ni{[type: Ethernet[], state: CONNECTED/CONNECTED, reason: (unspecified), extra: e8:11:ca:03:da:07, failover: false, available: true, roaming: false]}  network{101}  nethandle{437197393933}  lp{{InterfaceName: eth0 LinkAddresses: [ 192.168.40.30/24 ] DnsAddresses: [ /8.8.8.8 ] Domains: 192.168.40.1 MTU: 0 TcpBufferSizes: 524288,1048576,3145728,524288,1048576,2097152 Routes: [ 192.168.40.0/24 -> 0.0.0.0 eth0,255.255.255.255/32 -> 0.0.0.0 eth0,0.0.0.0/0 -> 255.255.255.255 eth0 ]}}  nc{[ Transports: ETHERNET Capabilities: NOT_METERED&INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VPN&NOT_ROAMING&FOREGROUND&NOT_CONGESTED&NOT_SUSPENDED LinkUpBandwidth>=100000Kbps LinkDnBandwidth>=100000Kbps]}  Score{0}  everValidated{false}  lastValidated{false}  created{false} lingering{false} explicitlySelected{false} acceptUnvalidated{false} everCaptivePortalDetected{false} lastCaptivePortalDetected{false} captivePortalValidationPending{false} partialConnectivity{false} acceptPartialConnectivity{false} clat{mBaseIface: null, mIface: null, mState: IDLE} }
2020-05-29 10:07:59.545 1078-1373/system_process D/MtkConnectivityService: NetworkAgentInfo [Ethernet () - 101] EVENT_NETWORK_INFO_CHANGED, going from initial to CONNECTED
2020-05-29 10:07:59.550 1078-1373/system_process D/MtkConnectivityService: Setting DNS servers for network 101 to [/8.8.8.8]
2020-05-29 10:07:59.555 1078-1373/system_process D/MtkConnectivityService: Adding iface eth0 to network 101
2020-05-29 10:07:59.570 1078-1373/system_process D/MtkConnectivityService: Setting DNS servers for network 101 to [/8.8.8.8]
2020-05-29 10:07:59.594 1078-1373/system_process D/MtkConnectivityService: Switching to new default network: NetworkAgentInfo{ ni{[type: Ethernet[], state: CONNECTED/CONNECTED, reason: (unspecified), extra: e8:11:ca:03:da:07, failover: false, available: true, roaming: false]}  network{101}  nethandle{437197393933}  lp{{InterfaceName: eth0 LinkAddresses: [ 192.168.40.30/24 ] DnsAddresses: [ /8.8.8.8 ] Domains: 192.168.40.1 MTU: 0 TcpBufferSizes: 524288,1048576,3145728,524288,1048576,2097152 Routes: [ 192.168.40.0/24 -> 0.0.0.0 eth0,255.255.255.255/32 -> 0.0.0.0 eth0,0.0.0.0/0 -> 255.255.255.255 eth0 ]}}  nc{[ Transports: ETHERNET Capabilities: NOT_METERED&INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VPN&NOT_ROAMING&FOREGROUND&NOT_CONGESTED&NOT_SUSPENDED LinkUpBandwidth>=100000Kbps LinkDnBandwidth>=100000Kbps]}  Score{0}  everValidated{false}  lastValidated{false}  created{true} lingering{false} explicitlySelected{false} acceptUnvalidated{false} everCaptivePortalDetected{false} lastCaptivePortalDetected{false} captivePortalValidationPending{false} partialConnectivity{false} acceptPartialConnectivity{false} clat{mBaseIface: null, mIface: null, mState: IDLE} }
2020-05-29 10:07:59.624 1078-1373/system_process D/MtkConnectivityService: Sending CONNECTED broadcast for type 9 NetworkAgentInfo [Ethernet () - 101] isDefaultNetwork=true

理解下大意为你保存了一个默认网络配置信息(new default network)后,发送 connected 通知出去,所以图标就显示出来了。

这是什么骚操作,一看日志tag就知道是 mkt 自己加的,搜索去看下源码


vendor\mediatek\proprietary\frameworks\opt\net\services\core\java\com\android\server\MtkConnectivityService.java

 /** Adds the given network to the specified legacy type list. */
        public void add(int type, NetworkAgentInfo nai) {
            if (!isTypeSupported(type)) {
                return;  // Invalid network type.
            }
            if (VDBG) log("Adding agent " + nai + " for legacy network type " + type);
            ArrayList<NetworkAgentInfo> list = mTypeLists[type];
            if (list.contains(nai)) {
                return;
            }
            synchronized (mTypeLists) {
                list.add(nai);
            }
            // Send a broadcast if this is the first network of its type or if it's the default.
            final boolean isDefaultNetwork = mService.isDefaultNetwork(nai);
            if ((list.size() == 1) || isDefaultNetwork) {
                maybeLogBroadcast(nai, DetailedState.CONNECTED, type, isDefaultNetwork);
                mService.sendLegacyNetworkBroadcast(nai, DetailedState.CONNECTED, type);
            }
        }


可以看到当网络列表集合只有一个配置,或是默认网络时,发送 CONNECTED 通知。开始我以为把这里加入网线状态判断后再发送

通知,后来尝试后发现并不行,那就转战应用层去处理这个bug吧。


解决思路


找到网卡图标显示的逻辑,当收到 CONNECTED 通知时同时判断网线是否已经插入,未插入则无效消息,不显示图标


那么问题来了,怎么知道网线是否已经插入或拨出呢。一般来讲这都需要驱动通过gpio口控制监听发送按键消息或


其它通知给上层。分析网线插入拨出相关日志,我发现在 framework 层中就能干这个活,EthernetTracker 中


就已经监听了网口状态。来看下日志

拔出
2020-05-29 09:03:55.847 1104-1131/? I/EthernetTracker: interfaceLinkStateChanged, iface: wlan0, up: false
2020-05-29 09:03:55.848 1104-1447/? E/EthernetTracker: updateInterfaceState up==false modified=false
2020-05-29 09:03:55.847 1104-1131/? I/EthernetTracker: interfaceLinkStateChanged, iface: eth0, up: false
2020-05-29 09:03:55.848 1104-1447/? E/EthernetTracker: updateInterfaceState up==false modified=false
插入
2020-05-29 09:04:55.847 1104-1131/? I/EthernetTracker: interfaceLinkStateChanged, iface: eth0, up: true
2020-05-29 09:04:55.848 1104-1447/? E/EthernetTracker: updateInterfaceState up==true modified=false

主要通过 NetworkManagementService 注册 InterfaceObserver,当网络状态改变时收到实时响应。


frameworks\opt\net\ethernet\java\com\android\server\ethernet\EthernetTracker.java

private class InterfaceObserver extends BaseNetworkObserver {
        @Override
        public void interfaceLinkStateChanged(String iface, boolean up) {
            if (DBG) {
                Log.i(TAG, "interfaceLinkStateChanged, iface: " + iface + ", up: " + up);
            }
            mHandler.post(() -> updateInterfaceState(iface, up));
        }
        @Override
        public void interfaceAdded(String iface) {
            mHandler.post(() -> maybeTrackInterface(iface));
        }
        @Override
        public void interfaceRemoved(String iface) {
            mHandler.post(() -> removeInterface(iface));
        }
    }
  private void updateInterfaceState(String iface, boolean up) {
        boolean modified = mFactory.updateInterfaceLinkState(iface, up);
        Log.e(TAG, "updateInterfaceState up==" + up + " modified="+modified);
        //cczheng add sys.ethernet.up for listen netline in or out 
        if ("eth0".equals(iface)) {
            android.os.SystemProperties.set("sys.ethernet.up", String.valueOf(up));
        }//E
        if (modified) {
            boolean restricted = isRestrictedInterface(iface);
            int n = mListeners.beginBroadcast();
            for (int i = 0; i < n; i++) {
                try {
                    if (restricted) {
                        ListenerInfo listenerInfo = (ListenerInfo) mListeners.getBroadcastCookie(i);
                        if (!listenerInfo.canUseRestrictedNetworks) {
                            continue;
                        }
                    }
                    mListeners.getBroadcastItem(i).onAvailabilityChanged(iface, up);
                } catch (RemoteException e) {
                    // Do nothing here.
                }
            }
            mListeners.finishBroadcast();
        }
    }

可以看到我在 updateInterfaceState() 中增加了 prop 保存网线插拔状态,为啥选用 prop 保存呢?因为网卡图标显示在


SystemUI 中,算是跨应用通讯吧,prop 简单方便,就不用 Settings.System/Global 之类的了。接下来修改 SystemUI


网卡图标显示监听在 EthernetSignalController 中


vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\statusbar\policy\EthernetSignalController.java

 @Override
    public void updateConnectivity(BitSet connectedTransports, BitSet validatedTransports) {
        mCurrentState.connected = connectedTransports.get(mTransportType);
        super.updateConnectivity(connectedTransports, validatedTransports);
    }
    @Override
    public void notifyListeners(SignalCallback callback) {
        boolean ethernetVisible = mCurrentState.connected;
        String contentDescription = getStringIfExists(getContentDescription());
        cczheng add visible for fix ethernet staticip set don't inset netline show bug
        android.util.Log.e("MtkConnectivityService", " systemui ethernetVisible="+ethernetVisible + " contentDescription="+contentDescription);
        boolean netLineIn = android.os.SystemProperties.getBoolean("sys.ethernet.up", false);
        android.util.Log.e("MtkConnectivityService", " systemui EthernetSignalController netline state ="+netLineIn);
        if (ethernetVisible){
            ethernetVisible = netLineIn;
            android.util.Log.e("MtkConnectivityService", "new ethernetVisible="+ethernetVisible);
        }//E
        // TODO: wire up data transfer using WifiSignalPoller.
        callback.setEthernetIndicators(new IconState(ethernetVisible, getCurrentIconId(),
                contentDescription));
    }
网线未插入情况,点击设置静态ip收到的日志
2020-05-30 09:19:29.089 1456-1676/com.android.systemui E/MtkConnectivityService:  systemui ethernetVisible=true contentDescription=以太网已断开连接。
2020-05-30 09:19:29.089 1456-1676/com.android.systemui E/MtkConnectivityService:  systemui EthernetSignalController netline state =false
网线插入,点击设置静态ip收到的日志
2020-05-30 09:19:29.089 1456-1676/com.android.systemui E/MtkConnectivityService:  systemui ethernetVisible=true contentDescription=以太网已断开连接。
2020-05-30 09:19:29.089 1456-1676/com.android.systemui E/MtkConnectivityService:  systemui EthernetSignalController netline state =true


可以看到我们需要过滤网线未插入收到的无效消息,读取网线状态 sys.ethernet.up 布尔值,当 ethernetVisible 为 true 时,校验状态


这样改完后测试发现还有坑,坑在真正 setIconVisibility 地方,也就是 StatusBarSignalPolicy


vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\statusbar\phone\StatusBarSignalPolicy.java

  @Override
    public void setEthernetIndicators(IconState state) {
        boolean visible = state.visible && !mBlockEthernet;
        int resId = state.icon;
        String description = state.contentDescription;
        //cczheng add visible for fix ethernet staticip set don't inset netline show bug
        if (visible && resId > 0) {
        //if (resId > 0) {
            mIconController.setIcon(mSlotEthernet, resId, description);
            mIconController.setIconVisibility(mSlotEthernet, true);
        } else {
            mIconController.setIconVisibility(mSlotEthernet, false);
        }
    }

发现了吗,传递进来的 visible 根本就没用上,这是什么大坑啊,将 visible 作为判断依据即可。


好了,这样 bug 就解决了,收工。


20200720 增加更新


网络优先级设置

网卡 > wifi > 4G

frameworks\opt\net\ethernet\java\com\android\server\ethernet\EthernetNetworkFactory.java

public class EthernetNetworkFactory extends NetworkFactory {
    private final static String TAG = EthernetNetworkFactory.class.getSimpleName();
    final static boolean DBG = true;
    private final static int NETWORK_SCORE = 110;
    private static final String NETWORK_TYPE = "Ethernet";
  ....
  private static final SparseArray<TransportInfo> sTransports = new SparseArray();
        static {
            // LowpanInterfaceTracker.NETWORK_SCORE
            sTransports.put(NetworkCapabilities.TRANSPORT_LOWPAN,
                    new TransportInfo(ConnectivityManager.TYPE_NONE, 30));
            // WifiAwareDataPathStateManager.NETWORK_FACTORY_SCORE_AVAIL
            sTransports.put(NetworkCapabilities.TRANSPORT_WIFI_AWARE,
                    new TransportInfo(ConnectivityManager.TYPE_NONE, 1));
            // EthernetNetworkFactory.NETWORK_SCORE
            sTransports.put(NetworkCapabilities.TRANSPORT_ETHERNET,
                    new TransportInfo(ConnectivityManager.TYPE_ETHERNET, NETWORK_SCORE));//70
            // BluetoothTetheringNetworkFactory.NETWORK_SCORE
            sTransports.put(NetworkCapabilities.TRANSPORT_BLUETOOTH,
                    new TransportInfo(ConnectivityManager.TYPE_BLUETOOTH, 69));
            // WifiNetworkFactory.SCORE_FILTER / NetworkAgent.WIFI_BASE_SCORE
            sTransports.put(NetworkCapabilities.TRANSPORT_WIFI,
                    new TransportInfo(ConnectivityManager.TYPE_WIFI, 60));
            // TelephonyNetworkFactory.TELEPHONY_NETWORK_SCORE
            sTransports.put(NetworkCapabilities.TRANSPORT_CELLULAR,
                    new TransportInfo(ConnectivityManager.TYPE_MOBILE, 50));
     }


TRANSPORT_LOWPAN 低速无限个域网 比分 30


TRANSPORT_WIFI_AWARE wifi相邻设备发现 比分 1


TRANSPORT_ETHERNET 网卡 比分 70


TRANSPORT_BLUETOOTH 蓝牙 比分 69


TRANSPORT_WIFI wifi 比分 60


TRANSPORT_CELLULAR 移动网络 比分 50


按照以往经验只修改 NETWORK_SCORE 值从 70 改成 110 是不行的,有隐藏的坑。


还需要修改 ConnectivityManager.TYPE_ETHERNET 对应赋值为 NETWORK_SCORE


因为获取 getNetworkScore() 方法如下

 private int getNetworkScore() {
            // never set the network score below 0.
            if (!mLinkUp) {
                 Log.e(TAG, " getNetworkScore mLinkUp false");
                return 0;
            }
            int[] transportTypes = mCapabilities.getTransportTypes();
            if (transportTypes.length < 1) {
                Log.w(TAG, "Network interface '" + mLinkProperties.getInterfaceName() + "' has no "
                        + "transport type associated with it. Score set to zero");
                return 0;
            }
            TransportInfo transportInfo = sTransports.get(transportTypes[0], /* if dne */ null);
            if (transportInfo != null) {
                Log.e(TAG, " getNetworkScore transportInfo.mScore="+transportInfo.mScore);
                return transportInfo.mScore;
            }
            return 0;
        }

如果只修改 NETWORK_SCORE=110,你会神奇的发现,当网卡接入局域网时,不能上外网时,打开SIM卡流量开关,

网卡图标消失了,而且网络自动切换到移动网络了。感觉很人性化有没有,可是我并不想要帮我自动切换到移动网络啊。

来看问题日志

局域网转移动网络
2020-07-20 11:38:37.933 1101-1742/system_process D/MtkConnectivityService: currentScore = 30, newScore = 50
2020-07-20 11:38:37.933 1101-1742/system_process D/MtkConnectivityService: rematch for NetworkAgentInfo [MOBILE (LTE) - 104]
2020-07-20 11:38:37.933 1101-1742/system_process D/MtkConnectivityService:    accepting network in place of null
2020-07-20 11:38:37.934 1101-1742/system_process D/MtkConnectivityService: sending new Min Network Score(50): NetworkRequest [ REQUEST id=1, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VPN] ]
2020-07-20 11:38:37.945 1101-1742/system_process D/MtkConnectivityService: Switching to new default network: NetworkAgentInfo{ ni{[type: MOBILE[LTE], state: CONNECTED/CONNECTED, reason: connected, extra: ctnet, failover: false, available: true, roaming: false]}  network{104}  nethandle{450082295821}  lp{{InterfaceName: ccmni1 LinkAddresses: [ 10.53.196.22/32,240e:ba:c806:8619::1/64 ] DnsAddresses: [ /240e:4e::66,/240e:4e:800::66,/219.146.1.66,/219.147.1.66 ] Domains: null MTU: 1460 TcpBufferSizes: 2097152,4194304,8388608,262144,524288,1048576 Routes: [ 0.0.0.0/0 -> 10.53.196.22 ccmni1,::/0 -> :: ccmni1,10.53.196.22/32 -> 0.0.0.0 ccmni1,240e:ba:c806:8619::/64 -> :: ccmni1 ]}}  nc{[ Transports: CELLULAR Capabilities: XCAP&INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VPN&VALIDATED&NOT_ROAMING&NOT_CONGESTED&NOT_SUSPENDED LinkUpBandwidth>=51200Kbps LinkDnBandwidth>=102400Kbps Specifier: <1>]}  Score{50}  everValidated{true}  lastValidated{true}  created{true} lingering{false} explicitlySelected{false} acceptUnvalidated{false} everCaptivePortalDetected{false} lastCaptivePortalDetected{false} captivePortalValidationPending{false} partialConnectivity{false} acceptPartialConnectivity{false} clat{mBaseIface: null, mIface: null, mState: IDLE} }
开机默认局域网情况
2020-07-20 17:13:46.916 1101-1742/system_process D/MtkConnectivityService: currentScore = 0, newScore = 30
2020-07-20 17:13:46.916 1101-1742/system_process D/MtkConnectivityService: rematch for NetworkAgentInfo [Ethernet  - 106]
2020-07-20 17:13:46.916 1087-1380/system_process D/MtkConnectivityService: Switching to new default network: NetworkAgentInfo{ ni{[type: Ethernet[], state: CONNECTED/CONNECTED, reason: (unspecified), extra: e8:11:ca:03:53:98, failover: false, available: true, roaming: false]}  network{100}  nethandle{432902426637}  lp{{InterfaceName: eth0 LinkAddresses: [ fe80::3c1a:67e3:a3cb:4b59/64,192.168.1.114/24 ] DnsAddresses: [ /8.8.8.8,/192.168.1.1 ] Domains: null MTU: 0 TcpBufferSizes: 524288,1048576,3145728,524288,1048576,2097152 Routes: [ fe80::/64 -> :: eth0,192.168.1.0/24 -> 0.0.0.0 eth0,0.0.0.0/0 -> 192.168.1.1 eth0 ]}}  nc{[ Transports: ETHERNET Capabilities: NOT_METERED&INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VPN&NOT_ROAMING&FOREGROUND&NOT_CONGESTED&NOT_SUSPENDED LinkUpBandwidth>=100000Kbps LinkDnBandwidth>=100000Kbps]}  Score{30}  everValidated{false}  lastValidated{false}  created{true} lingering{false} explicitlySelected{false} acceptUnvalidated{false} everCaptivePortalDetected{false} lastCaptivePortalDetected{false} captivePortalValidationPending{false} partialConnectivity{false} acceptPartialConnectivity{false} clat{mBaseIface: null, mIface: null, mState: IDLE} }

搜索 Switching to new default 关键字,找到 MtkConnectivityService.java 好吧又是这货


vendor\mediatek\proprietary\frameworks\opt\net\services\core\java\com\android\server\MtkConnectivityService.java


private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork,
            ReapUnvalidatedNetworks reapUnvalidatedNetworks, long now) {
        if (!newNetwork.everConnected) return;
        boolean keep = newNetwork.isVPN();
        boolean isNewDefault = false;
        NetworkAgentInfo oldDefaultNetwork = null;
        final boolean wasBackgroundNetwork = newNetwork.isBackgroundNetwork();
        final int score = newNetwork.getCurrentScore();
    .....
     if (VDBG || DDBG) {
                    log("currentScore = " +
                            (currentNetwork != null ? currentNetwork.getCurrentScore() : 0) +
                            ", newScore = " + score);
                }


看到上面打印 newScore 值来自 newNetwork.getCurrentScore() 方法,搜索找到 NetworkAgentInfo.java 中


frameworks\base\services\core\java\com\android\server\connectivity\NetworkAgentInfo.java


private int getCurrentScore(boolean pretendValidated) {
        // TODO: We may want to refactor this into a NetworkScore class that takes a base score from
        // the NetworkAgent and signals from the NetworkAgent and uses those signals to modify the
        // score.  The NetworkScore class would provide a nice place to centralize score constants
        // so they are not scattered about the transports.
        // If this network is explicitly selected and the user has decided to use it even if it's
        // unvalidated, give it the maximum score. Also give it the maximum score if it's explicitly
        // selected and we're trying to see what its score could be. This ensures that we don't tear
        // down an explicitly selected network before the user gets a chance to prefer it when
        // a higher-scoring network (e.g., Ethernet) is available.
        if (networkMisc.explicitlySelected && (networkMisc.acceptUnvalidated || pretendValidated)) {
            return ConnectivityConstants.EXPLICITLY_SELECTED_NETWORK_SCORE;
        }
        int score = currentScore;
        if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty() && !isVPN()) {
            score -= ConnectivityConstants.UNVALIDATED_SCORE_PENALTY;
        }
        if (score < 0) score = 0;
        return score;
    }


一直好奇上面的网卡 30 分是怎么来的?看到这里就明白了,我们修改的 NETWORK_SCORE=110 并没有用,实际取得是 sTransports 中


70,然后在 getCurrentScore() 中由于网络不是有效的能上网网络,则需要减去 UNVALIDATED_SCORE_PENALTY 40


30 = sTransports.TRANSPORT_ETHERNET - UNVALIDATED_SCORE_PENALTY


frameworks\base\services\core\java\com\android\server\connectivity\ConnectivityConstants.java

public class ConnectivityConstants {
    // Penalty applied to scores of Networks that have not been validated.
    public static final int UNVALIDATED_SCORE_PENALTY = 40;
    // Score for explicitly connected network.
    //
    // This ensures that a) the explicitly selected network is never trumped by anything else, and
    // b) the explicitly selected network is never torn down.
    public static final int EXPLICITLY_SELECTED_NETWORK_SCORE = 100;
    // VPNs typically have priority over other networks. Give them a score that will
    // let them win every single time.
    public static final int VPN_DEFAULT_SCORE = 101;
}

这样问题就搞清楚了。还有坑在 wifi 和 局域网同时连接,wifi 图标依旧显示,修改如下地方即可


vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java

@@ -89,8 +89,12 @@ public class WifiSignalController extends
         // only show wifi in the cluster if connected or if wifi-only
         boolean visibleWhenEnabled = mContext.getResources().getBoolean(
                 R.bool.config_showWifiIndicatorWhenEnabled);
         Log.v(TAG,"mCurrentState.inetCondition = " + mCurrentState.inetCondition);
         boolean wifiVisible = mCurrentState.enabled
                && (mCurrentState.connected || !mHasMobileData || visibleWhenEnabled)
                && (mCurrentState.inetCondition == 1);
         //cczheng add mCurrentState.inetCondition == 1 for fix eth icon and wifi icon same show
         String wifiDesc = wifiVisible ? mCurrentState.ssid : null;
         boolean ssidPresent = wifiVisible && mCurrentState.ssid != null;
         String contentDescription = getStringIfExists(getContentDescription());


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
1月前
|
Java Android开发 Swift
安卓与iOS开发对比:平台选择对项目成功的影响
【10月更文挑战第4天】在移动应用开发的世界中,选择合适的平台是至关重要的。本文将深入探讨安卓和iOS两大主流平台的开发环境、用户基础、市场份额和开发成本等方面的差异,并分析这些差异如何影响项目的最终成果。通过比较这两个平台的优势与挑战,开发者可以更好地决定哪个平台更适合他们的项目需求。
109 1
|
2月前
|
IDE Android开发 iOS开发
探索Android与iOS开发的差异:平台选择对项目成功的影响
【9月更文挑战第27天】在移动应用开发的世界中,Android和iOS是两个主要的操作系统平台。每个系统都有其独特的开发环境、工具和用户群体。本文将深入探讨这两个平台的关键差异点,并分析这些差异如何影响应用的性能、用户体验和最终的市场表现。通过对比分析,我们将揭示选择正确的开发平台对于确保项目成功的重要作用。
|
1月前
|
Android开发
Android开发表情emoji功能开发
本文介绍了一种在Android应用中实现emoji表情功能的方法,通过将图片与表情字符对应,实现在`TextView`中的正常显示。示例代码展示了如何使用自定义适配器加载emoji表情,并在编辑框中输入或删除表情。项目包含完整的源码结构,可作为开发参考。视频演示和源码详情见文章内链接。
67 4
Android开发表情emoji功能开发
|
22天前
|
安全 Android开发 iOS开发
Android vs iOS:探索移动操作系统的设计与功能差异###
【10月更文挑战第20天】 本文深入分析了Android和iOS两个主流移动操作系统在设计哲学、用户体验、技术架构等方面的显著差异。通过对比,揭示了这两种系统各自的独特优势与局限性,并探讨了它们如何塑造了我们的数字生活方式。无论你是开发者还是普通用户,理解这些差异都有助于更好地选择和使用你的移动设备。 ###
43 3
|
29天前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
81 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
2月前
|
开发工具 Android开发 iOS开发
安卓与iOS开发环境对比:选择适合你的平台
【9月更文挑战第26天】在移动应用开发的广阔天地中,安卓和iOS是两大巨头。它们各自拥有独特的优势和挑战,影响着开发者的选择和决策。本文将深入探讨这两个平台的开发环境,帮助你理解它们的核心差异,并指导你根据个人或项目需求做出明智的选择。无论你是初学者还是资深开发者,了解这些平台的异同都至关重要。让我们一起探索,找到最适合你的那片开发天地。
|
2月前
|
Android开发 开发者
Android平台无纸化同屏如何实现实时录像功能
Android平台无纸化同屏,如果需要本地录像的话,实现难度不大,只要复用之前开发的录像模块的就可以,对我们来说,同屏采集这块,只是数据源不同而已,如果是自采集的其他数据,我们一样可以编码录像。
|
2月前
|
安全 API 开发工具
Android平台RTMP推送|轻量级RTSP服务如何实现麦克风|扬声器声音采集切换
Android平台扬声器播放声音的采集,在无纸化同屏等场景下,意义很大,早期低版本的Android设备,是没法直接采集扬声器audio的(从Android 10开始支持),所以,如果需要采集扬声器audio,需要先做系统版本判断,添加相应的权限。
|
3天前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。
|
5天前
|
Android开发 Swift iOS开发
探索安卓与iOS开发的差异和挑战
【10月更文挑战第37天】在移动应用开发的广阔舞台上,安卓和iOS这两大操作系统扮演着主角。它们各自拥有独特的特性、优势以及面临的开发挑战。本文将深入探讨这两个平台在开发过程中的主要差异,从编程语言到用户界面设计,再到市场分布的不同影响,旨在为开发者提供一个全面的视角,帮助他们更好地理解并应对在不同平台上进行应用开发时可能遇到的难题和机遇。