当前位置:   article > 正文

Android网络优先级及更改_android studio 设置网络通讯的优先级

android studio 设置网络通讯的优先级

Android版本:

Android 4.4.4

涉及内容:

  1. 1,网络优先级;
  2. 2,网络切换;
  3. 3,界面显示。

解决问题:

  1. 1,更改网络优先级:让以太网(eth0)优先级高于WiFi(Wlan0);
  2. 2,WiFi切换到以太网异常原因及解决。

一、 网络优先级
1、 Android支持的网络类型
Android系统framework层的ConnectivityManager.java文件中 定义了支持的所有网络类型:
  1. frameworks\base\core\java\android\net\ConnectivityManager.java
  2. public static final int TYPE_MOBILE = 0;
  3. public static final int TYPE_WIFI = 1;
  4. public static final int TYPE_MOBILE_MMS = 2;
  5. public static final int TYPE_MOBILE_SUPL = 3;
  6. public static final int TYPE_MOBILE_DUN = 4;
  7. public static final int TYPE_MOBILE_HIPRI = 5;
  8. public static final int TYPE_WIMAX = 6;
  9. public static final int TYPE_BLUETOOTH = 7;
  10. public static final int TYPE_DUMMY = 8;
  11. public static final int TYPE_ETHERNET = 9;
  12. public static final int TYPE_MOBILE_FOTA = 10;
  13. public static final int TYPE_MOBILE_IMS = 11;
  14. public static final int TYPE_MOBILE_CBS = 12;
  15. public static final int TYPE_WIFI_P2P = 13;

对于上网,接触的几乎都是 TYPE_WIFITYPE_MOBILE、TYPE_ETHERNET这三种。
这些网络的优先级定义在config.xml文件的networkAttributes数组 中:
  1. frameworks\base\core\res\res\values\config.xml
  2. <!-- This string array should be overridden by the device to present a list of network attributes, based on the hardware -->
  3. <string-array translatable="false" name="networkAttributes">
  4. <item>"wifi,1,1,1,-1,true"</item>
  5. <item>"mobile,0,0,0,-1,true"</item>
  6. <item>"mobile_mms,2,0,2,60000,true"</item>
  7. <item>"mobile_supl,3,0,2,60000,true"</item>
  8. <item>"mobile_hipri,5,0,3,60000,true"</item>
  9. <item>"mobile_fota,10,0,2,60000,true"</item>
  10. <item>"mobile_ims,11,0,2,60000,true"</item>
  11. <item>"mobile_cbs,12,0,2,60000,true"</item>
  12. <item>"wifi_p2p,13,1,0,-1,true"</item>
  13. <item>"mobile_ia,14,0,2,-1,true"</item>
  14. <item>"bluetooth,7,7,1,60000,true"</item>
  15. <item>"eth,9,9,4,60000,true"</item>
  16. </string-array>

注意 networkAttributes数组前的注释!
大意是说,对某种网络支持与否取决与硬件,所以该文件会被源码目录/device/下的config.xml定义的 networkAttributes数组覆盖!!!
也就是说,真正起作用的优先级配置在 源码目录/device/ 下的config.xml中定义。

对于 networkAttributes数组的每一个item:
<item>"wifi,1,1,1,-1,true"</item>
其含义由 NetworkConfig.java描述(一一对应):

  1. frameworks\base\core\java\android\net\NetworkConfig.java
  2. public class NetworkConfig {
  3. /**
  4. * Human readable string
  5. */
  6. public String name;
  7. /**
  8. * Type from ConnectivityManager
  9. */
  10. public int type;
  11. /**
  12. * the radio number from radio attributes config
  13. */
  14. public int radio;
  15. /**
  16. * higher number == higher priority when turning off connections
  17. */
  18. public int priority;
  19. /**
  20. * indicates the boot time dependencyMet setting
  21. */
  22. public boolean dependencyMet;
  23. /**
  24. * indicates the default restoral timer in seconds
  25. * if the network is used as a special network feature
  26. * -1 indicates no restoration of default
  27. */
  28. public int restoreTime;
  29. /**
  30. * input string from config.xml resource. Uses the form:
  31. * [Connection name],[ConnectivityManager connection type],
  32. * [associated radio-type],[priority],[dependencyMet]
  33. */
  34. public NetworkConfig(String init) {
  35. String fragments[] = init.split(",");
  36. name = fragments[0].trim().toLowerCase(Locale.ROOT);
  37. type = Integer.parseInt(fragments[1]);
  38. radio = Integer.parseInt(fragments[2]);
  39. priority = Integer.parseInt(fragments[3]);
  40. restoreTime = Integer.parseInt(fragments[4]);
  41. dependencyMet = Boolean.parseBoolean(fragments[5]);
  42. }
  43. }

2、更改以太网优先级高于WiFi

<item>"eth,9,9,0,60000,true"</item>
并设置 Preferred网络为以太网:
  1. frameworks\base\services\java\com\android\server\ConnectivityService.java
  2. mNetworkPreference = getPersistedNetworkPreference();
  3. private int getPersistedNetworkPreference() {
  4. final ContentResolver cr = mContext.getContentResolver();
  5. // 设置Preferred网络为TYPE_ETHERNET
  6. Settings.Global.putInt(cr, Settings.Global.NETWORK_PREFERENCE, ConnectivityManager.TYPE_ETHERNET);
  7. final int networkPrefSetting = Settings.Global
  8. .getInt(cr, Settings.Global.NETWORK_PREFERENCE, -1);
  9. log("networkPrefSetting: " + networkPrefSetting);
  10. if (networkPrefSetting != -1) {
  11. return networkPrefSetting;
  12. }
  13. return ConnectivityManager.DEFAULT_NETWORK_PREFERENCE;
  14. }

3、网络优先级的读取

  1. frameworks\base\services\java\com\android\server\ConnectivityService.java
  2. public ConnectivityService() {
  3. if (DBG) log("ConnectivityService starting up");
  4. boolean wifiOnly = SystemProperties.getBoolean("ro.radio.noril", false);
  5. log("wifiOnly=" + wifiOnly);
  6. String[] naStrings = context.getResources().getStringArray(com.android.internal.R.array.networkAttributes);
  7. for (String naString : naStrings) {
  8. try {
  9. NetworkConfig n = new NetworkConfig(naString);
  10. if (VDBG) log("naString=" + naString + " config=" + n);
  11. mNetConfigs[n.type] = n;
  12. mNetworksDefined++;
  13. }
  14. }
  15. }

Log如下:



二、 网络切换
现在,优先级:Ethernet > WiFi,在WiFi连接的情况下,点击【使用以太网】按钮进行网络切换:
先响应一个EVENT_CONFIGURATION_CHANGED事件:
  1. frameworks\base\services\java\com\android\server\ConnectivityService.java
  2. case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED: {
  3. info = (NetworkInfo) msg.obj;
  4. handleConnectivityChange(info.getType(), false);
  5. break;
  6. }

对网络是否切换的仲裁在 handleConnect()方法中调用的 isNewNetTypePreferredOverCurrentNetType()方法:

  1. frameworks\base\services\java\com\android\server\ConnectivityService.java
  2. private void handleConnect(NetworkInfo info) {
  3. final int newNetType = info.getType();
  4. if (VDBG) {
  5. log("handleConnect: E newNetType=" + newNetType + " thisIface=" + thisIface
  6. + " isFailover" + isFailover);
  7. }
  8. // if this is a default net and other default is running
  9. // kill the one not preferred
  10. if (mNetConfigs[newNetType].isDefault()) {
  11. if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != newNetType) {
  12. if (isNewNetTypePreferredOverCurrentNetType(newNetType)) {
  13. // tear down the other
  14. NetworkStateTracker otherNet =mNetTrackers[mActiveDefaultNetwork];
  15. if (DBG) {
  16. log("Policy requires " + otherNet.getNetworkInfo().getTypeName() +
  17. " teardown");
  18. }
  19. if (!teardown(otherNet)) {
  20. loge("Network declined teardown request");
  21. teardown(thisNet);
  22. return;
  23. }
  24. } else {
  25. // don't accept this one
  26. if (VDBG) {
  27. log("Not broadcasting CONNECT_ACTION " +
  28. "to torn down network " + info.getTypeName());
  29. }
  30. teardown(thisNet);
  31. return;
  32. }
  33. }
  34. }
  35. }
  36. private boolean isNewNetTypePreferredOverCurrentNetType(int type) {
  37. log("type = "+ type);
  38. log("mNetworkPreference = " + mNetworkPreference);
  39. log("mActiveDefaultNetwork = " + mActiveDefaultNetwork);
  40. log("mNetConfigs[mActiveDefaultNetwork].priority = " + mNetConfigs[mActiveDefaultNetwork].priority);
  41. log("mNetConfigs[type].priority = " + mNetConfigs[type].priority);
  42. if (((type != mNetworkPreference)
  43. && (mNetConfigs[mActiveDefaultNetwork].priority > mNetConfigs[type].priority))
  44. || (mNetworkPreference == mActiveDefaultNetwork)) {
  45. log("return false");
  46. return false;
  47. }
  48. log("return true");
  49. return true;
  50. }

mNetworkPreference = 9,之前设置的Preferred网络。
mActiveDefaultNetwork = 1,当前使用的网络,即WiFi。
经过 isNewNetTypePreferredOverCurrentNetType()的仲裁,返回true进行网络切换:
Policy requires WIFI teardown

至此, Ethernet当道,WiFi让行。

三、界面显示
在【Settings-->以太网】界面,【使用以太网】选项一直处于连接状态且不可点击,IP地址等信息亦不见;此时进入Shell用ifconfig查看IP,
可知以太网IP等已经获取、且WiFi已经断掉、且ping网络正常。
原因去在Settings部分查找:

  1. packages\apps\settings\src\com\android\settings\ethernet\EthernetSettings.java
  2. public void getEthInfo(int state){
  3. if (state == EthernetDataTracker.ETHER_STATE_CONNECTING) {
  4. mUseEthernet.setEnabled(false);
  5. mUseEthernet.setSummary(R.string.ethernet_connecting);
  6. clearIpInfo();
  7. } else if (state == EthernetDataTracker.ETHER_STATE_DISCONNECTED) {
  8. mUseEthernet.setEnabled(true);
  9. mUseEthernet.setSummary(R.string.ethernet_unconnected);
  10. clearIpInfo();
  11. } else if (state == EthernetDataTracker.ETHER_STATE_CONNECTED) {
  12. mUseEthernet.setEnabled(true);
  13. mUseEthernet.setSummary(R.string.ethernet_connected);
  14. if(isUsingStaticIp()) {
  15. getEthInfoFromStaticIP();
  16. } else {
  17. getEthInfoFromDhcp();
  18. }
  19. mEthmac = getEthMac();
  20. }
  21. }

mUseEthernet不可用原因是以太网一 直处于 ETHER_STATE_CONNECTING 状态,以太网状态来自:
  1. packages\apps\settings\src\com\android\settings\ethernet\EthernetSettings.java
  2. private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
  3. @Override
  4. public void onReceive(Context context, Intent intent) {
  5. int state = intent.getIntExtra(EthernetDataTracker.EXTRA_ETHERNET_STATE, 0);
  6. Log.d(TAG, "BroadcastReceiver: Ethernet current state:" + state);
  7. getEthInfo(state);
  8. }
  9. };

广播发送地:
  1. frameworks\base\core\java\android\net\EthernetDataTracker.java
  2. private void runDhcp() {
  3. Log.d(TAG, "mIface = " + mIface + ", isEthernetEnabled() = " + isEthernetEnabled());
  4. if(!mIface.isEmpty() && isEthernetEnabled()) {
  5. registerEthernetContentObserver(); // register here when boot with plugged ethernet
  6. {
  7. // send connected msg only when wifi disconnect
  8. if(!IsWiFiConnected()) {
  9. sendEthStateChangedBroadcast(ETHER_STATE_CONNECTED);
  10. } else {
  11. Log.e(TAG, "WiFiConnected, cannot send ETHER_STATE_CONNECTED MSG");
  12. }
  13. }
  14. }
  15. }
  16. private Boolean IsWiFiConnected() {
  17. try {
  18. ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
  19. boolean isWiFiConnected = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected();
  20. Log.e(TAG, "isWiFiConnected: " + isWiFiConnected);
  21. return isWiFiConnected;
  22. }
  23. }

可知:虽然 WiFi已经被teardown,但IsWiFiConnected()依旧返回true,即WiFi状态没被更新:
  1. frameworks\base\wifi\java\android\net\wifi\WifiStateTracker.java
  2. public boolean teardown() {
  3. mTeardownRequested.set(true);
  4. mWifiManager.stopWifi();
  5. return true;
  6. }

IsWiFiConnected()运行先于WiFi的teardown(),所以在teardown()更改WiFi的状态是无效的。。。既然现在需要Ethernet优先级高于WiFi,直接让IsWiFiConnected()返回false即可。


Android 6.0 Wifi/Ethernet同时开默认动作
先连接WiFi,再开ethernet,WiFi会被系统自动的关掉:状态由connected->saved,log:

03-15 01:18:44.204   556   574 D Tethering: interfaceLinkStateChanged wlan0, true
03-15 01:18:44.205   556   574 D Tethering: interfaceStatusChanged wlan0, true
03-15 01:18:47.585   556   574 D Tethering: interfaceLinkStateChanged eth0, true
03-15 01:18:47.585   556   574 D Tethering: interfaceStatusChanged eth0, true
03-15 01:18:47.591   556   574 D EthernetNetworkFactory: updateInterface: eth0 link up
03-15 01:18:47.596   556  1806 I EthernetNetworkFactory: dhcpThread(eth0): mNetworkInfo=[type: Ethernet[], state: DISCONNECTED/DISCONNECTED, reason: (unspecified), extra: 00:23:9e:03:bd:aa, roaming: false, failover: false, isAvailable: true]
03-15 01:18:47.632  1807  1807 I dhcpcd  : version 5.5.6 starting
03-15 01:18:47.633  1807  1807 E dhcpcd  : get_duid: Read-only file system
03-15 01:18:47.738  1807  1807 I dhcpcd  : eth0: rebinding lease of 192.168.1.64
03-15 01:18:47.895  1807  1807 I dhcpcd  : eth0: acknowledged 192.168.1.64 from 192.168.1.250
03-15 01:18:47.942  1807  1807 I dhcpcd  : eth0: leased 192.168.1.64 for 86400 seconds
03-15 01:18:48.430   556  1806 D ConnectivityService: registerNetworkAgent NetworkAgentInfo{ ni{[type: Ethernet[], state: CONNECTED/CONNECTED, reason: (unspecified), extra: 00:23:9e:03:bd:aa, roaming: false, failover: false, isAvailable: true]}  network{116}  lp{<!-- -->{InterfaceName: eth0 LinkAddresses: [192.168.1.64/22,]  Routes: [192.168.0.0/22 -> 0.0.0.0 eth0,0.0.0.0/0 -> 192.168.1.250 eth0,] DnsAddresses: [192.168.1.250,] Domains:  MTU: 0 TcpBufferSizes: 524288,1048576,3145728,524288,1048576,2097152}}  nc{[ Transports: ETHERNET Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VPN LinkUpBandwidth>=100000Kbps LinkDnBandwidth>=100000Kbps]}  Score{110}  everValidated{false}  lastValidated{false}  created{false} lingering{false} explicitlySelected{false} acceptUnvalidated{false} everCaptivePortalDetected{false} lastCaptivePortalDetected{false} }
03-15 01:18:48.432   556   634 D ConnectivityService: NetworkAgentInfo [Ethernet () - 116] EVENT_NETWORK_INFO_CHANGED, going from null to CONNECTED
03-15 01:18:48.442   556   634 D ConnectivityService: Adding iface eth0 to network 116
03-15 01:18:48.496   556   634 E ConnectivityService: Unexpected mtu value: 0, eth0
03-15 01:18:48.496   556   634 D ConnectivityService: Adding Route [192.168.0.0/22 -> 0.0.0.0 eth0] to network 116
03-15 01:18:48.501   556   634 D ConnectivityService: Adding Route [0.0.0.0/0 -> 192.168.1.250 eth0] to network 116
03-15 01:18:48.506   556   634 D ConnectivityService: Setting Dns servers for network 116 to [/192.168.1.250]
03-15 01:18:48.532   556   634 D ConnectivityService: notifyType IP_CHANGED for NetworkAgentInfo [Ethernet () - 116]
03-15 01:18:48.550   556   634 D ConnectivityService: scheduleUnvalidatedPrompt 116
03-15 01:18:48.550   556   634 D ConnectivityService: updateSignalStrengthThresholds: CONNECT, sending [] to NetworkAgentInfo [Ethernet () - 116]
03-15 01:18:48.551   556   634 D ConnectivityService: rematch for NetworkAgentInfo [Ethernet () - 116]
03-15 01:18:48.551   556   634 D ConnectivityService:    accepting network in place of NetworkAgentInfo [WIFI () - 115]
03-15 01:18:48.552   556   634 D ConnectivityService: notifyType LOSING for NetworkAgentInfo [WIFI () - 115]
03-15 01:18:48.552   556  1797 D NetworkMonitor/NetworkAgentInfo [WIFI () - 115]: Lingering
03-15 01:18:48.559   556   634 D ConnectivityService: Switching to new default network: NetworkAgentInfo{ ni{[type: Ethernet[], state: CONNECTED/CONNECTED, reason: (unspecified), extra: 00:23:9e:03:bd:aa, roaming: false, failover: false, isAvailable: true]}  network{116}  lp{<!-- -->{InterfaceName: eth0 LinkAddresses: [192.168.1.64/22,]  Routes: [192.168.0.0/22 -> 0.0.0.0 eth0,0.0.0.0/0 -> 192.168.1.250 eth0,] DnsAddresses: [192.168.1.250,] Domains:  MTU: 0 TcpBufferSizes: 524288,1048576,3145728,524288,1048576,2097152}}  nc{[ Transports: ETHERNET Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VPN LinkUpBandwidth>=100000Kbps LinkDnBandwidth>=100000Kbps]}  Score{110}  everValidated{false}  lastValidated{false}  created{true} lingering{false} explicitlySelected{false} acceptUnvalidated{false} everCaptivePortalDetected{false} lastCaptivePortalDetected{false} }
03-15 01:18:48.562   556   634 D ConnectivityService: Setting tx/rx TCP buffers to 524288,1048576,3145728,524288,1048576,2097152
03-15 01:18:48.572   556   634 D CSLegacyTypeTracker: Sending DISCONNECTED broadcast for type 1 NetworkAgentInfo [WIFI () - 115] isDefaultNetwork=true
03-15 01:18:48.572   556   634 D ConnectivityService: sendStickyBroadcast: action=android.net.conn.CONNECTIVITY_CHANGE
03-15 01:18:48.574   556   634 D CSLegacyTypeTracker: Sending CONNECTED broadcast for type 9 NetworkAgentInfo [Ethernet () - 116] isDefaultNetwork=true
03-15 01:18:48.574   556   634 D ConnectivityService: sendStickyBroadcast: action=android.net.conn.CONNECTIVITY_CHANGE
03-15 01:18:48.574   556   556 D Tethering: Tethering got CONNECTIVITY_ACTION
03-15 01:18:48.575   556   577 D Tethering: MasterInitialState.processMessage what=3
03-15 01:18:48.582   556   634 D ConnectivityService: notifyType PRECHECK for NetworkAgentInfo [Ethernet () - 116]
03-15 01:18:48.582   556   556 D Tethering: Tethering got CONNECTIVITY_ACTION
03-15 01:18:48.583   556   577 D Tethering: MasterInitialState.processMessage what=3
03-15 01:18:48.588   556   634 D ConnectivityService: setProvNotificationVisibleIntent null visible=false networkType=MOBILE extraInfo=null highPriority=false
03-15 01:18:48.589   556   634 D ConnectivityService: NetworkAgentInfo [Ethernet () - 116] validation  passed
03-15 01:18:48.589   556   634 D ConnectivityService: notifyType CAP_CHANGED for NetworkAgentInfo [Ethernet () - 116]
03-15 01:18:48.600   556   634 D ConnectivityService: sendStickyBroadcast: action=android.net.conn.INET_CONDITION_ACTION
03-15 01:18:55.216   556   574 D Tethering: interfaceLinkStateChanged wlan0, true
03-15 01:18:55.216   556   574 D Tethering: interfaceStatusChanged wlan0, true
03-15 01:18:56.558   556   634 D ConnectivityService: handlePromptUnvalidated 116
03-15 01:19:13.857   556   632 D WifiStateMachine: starting scan for "360wifi-2"WPA_PSK with 2447
03-15 01:19:14.556   556   574 D Tethering: interfaceLinkStateChanged wlan0, true
03-15 01:19:14.557   556   574 D Tethering: interfaceStatusChanged wlan0, true
03-15 01:19:18.565   556   634 D ConnectivityService: handleLingerComplete for NetworkAgentInfo [WIFI () - 115]
03-15 01:19:18.566   556   632 D WifiNetworkAgent: NetworkAgent: NetworkAgent channel lost
03-15 01:19:18.567   556   634 D ConnectivityService: NetworkAgentInfo [WIFI () - 115] got DISCONNECTED, was satisfying 1
03-15 01:19:18.595   556   632 E WifiConfigStore: handleBadNetworkDisconnectReport (+8) 0 SSID: 360wifi-2, BSSID: f0:79:59:35:f0:5e, MAC: 58:63:56:f6:f2:ff, Supplicant state: COMPLETED, RSSI: -49, Link speed: 72Mbps, Frequency: 2447MHz, Net ID: 0, Metered hint: false, score: 60
03-15 01:19:18.608  1465  1465 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid=f0:79:59:35:f0:5e reason=3 locally_generated=1
03-15 01:19:18.612   556   574 D Tethering: interfaceLinkStateChanged wlan0, false
03-15 01:19:18.612   556   574 D Tethering: interfaceStatusChanged wlan0, false
03-15 01:19:18.613   556   577 D Tethering: InitialState.processMessage what=4
03-15 01:19:18.617   556   577 D Tethering: sendTetherStateChangedBroadcast 0, 0, 0
03-15 01:19:18.618   556   574 D Tethering: interfaceLinkStateChanged wlan0, false
03-15 01:19:18.618   556   574 D Tethering: interfaceStatusChanged wlan0, false
03-15 01:19:18.622   556   634 D ConnectivityService: notifyType LOST for NetworkAgentInfo [WIFI () - 115]
03-15 01:19:18.623   556   632 D WifiStateMachine: WifiStateMachine: Leaving Connected state
03-15 01:19:18.623   556   632 D WifiNative-HAL: stopRssiMonitoring, cmdId 0
03-15 01:19:18.623   556   632 E WifiConfigStore: saveWifiConfigBSSID Setting BSSID for "360wifi-2"WPA_PSK to any
03-15 01:19:18.638   556  1468 D DhcpClient: Clearing IP address
03-15 01:19:18.698   229   551 E Netd    : netlink response contains error (No such file or directory)
03-15 01:19:18.699   229   551 D CommandListener: Clearing all IP addresses on wlan0
03-15 01:19:18.700   229   551 D CommandListener: Setting iface cfg
03-15 01:19:18.703   556  1798 D DhcpClient: Receive thread stopped
03-15 01:19:18.711   556   632 E WifiConfigStore: saveWifiConfigBSSID Setting BSSID for "360wifi-2"WPA_PSK to any
03-15 01:19:18.723   556   632 D WifiStateMachine: Start Disconnecting Watchdog 13
03-15 01:19:18.732   556   632 D WifiNative-HAL: stopRssiMonitoring, cmdId 0
03-15 01:19:18.735   229   551 D CommandListener: Clearing all IP addresses on wlan0
03-15 01:19:18.847   556   632 D WifiConfigStore: Retrieve network priorities after PNO.
03-15 01:19:20.174   556   574 D Tethering: interfaceLinkStateChanged wlan0, false
03-15 01:19:20.174   556   574 D Tethering: interfaceStatusChanged wlan0, false
03-15 01:19:20.260   556   632 E WifiConfigStore:  rewrite network history for "360wifi-2"WPA_PSK

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/301857
推荐阅读
相关标签
  

闽ICP备14008679号