当前位置:   article > 正文

STA双WiFi连接_cmd wiif "add-suggestion

cmd wiif "add-suggestion

Wi-Fi STA/STA 并发Android 12 引入了 Wi-Fi STA/STA 并发功能,使设备可同时连接到两个 Wi-Fi 网络


1、STA/STA双WiFi开关

1.1 相关属性

packages/modules/Wifi/service/ServiceWifiResources/res/values/config.xml

<!-- Enable Make-Before-Break Wifi network switching.
     Note: this is conditional on the device supporting dual concurrent STAs. -->
<bool translatable="false" name="config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled">false</bool>
<!-- Enable concurrent peer to peer + internet connectivity
     Note: this is conditional on the device supporting dual concurrent STAs. -->
<bool translatable="false" name="config_wifiMultiStaLocalOnlyConcurrencyEnabled">false</bool>
<!-- Enable concurrent restricted connectivity + internet connectivity
     Note: this is conditional on the device supporting dual concurrent STAs. -->
<bool translatable="false" name="config_wifiMultiStaRestrictedConcurrencyEnabled">false</bool>
<!-- Enable concurrent internet connectivity + internet connectivity
     Note: this is conditional on the device supporting dual concurrent STAs. -->
<bool translatable="false" name="config_wifiMultiStaMultiInternetConcurrencyEnabled">false</bool>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

1.2 STA/STA支持判断

  • mWifiManager.isWifiEnabled() WIFI开关是否打开
  • mWifiManager.isStaConcurrencyForMultiInternetSupported() 属性config_wifiMultiStaMultiInternetConcurrencyEnabled配置
  • mWifiManager.getStaConcurrencyForMultiInternetMode() == WifiManager.WIFI_MULTI_INTERNET_MODE_MULTI_AP 模式双WIFI STA/STA开关是否打开(模式设置setStaConcurrencyForMultiInternetMode
  • WifiManager#WIFI_MULTI_INTERNET_MODE_DBS_AP:限制与 DBS AP 的双频的并发连接。
  • WifiManager#WIFI_MULTI_INTERNET_MODE_MULTI_AP:连接到任意 AP,其中的各个连接使用不同的频段。
  • WifiManager#WIFI_MULTI_INTERNET_MODE_DISABLED:停用功能。

2、STA双WiFi命令测试

adb shell cmd wifi
Android framework服务命令行工具框架 - Android13

packages/modules/Wifi/service/java/com/android/server/wifi/WifiShellCommand.java

  • 启用详细日志记录:adb shell cmd wifi set-verbose-logging enabled
  • 清理旧的wifi建议(如果有的话):adb shell cmd wifi remove-all-suggestions
    adb shell cmd wifi list-all-suggestions
  • WiFi连接状态查询:adb shell cmd wifi status | grep -E "==|connected to"
==== ClientModeManager instance: ConcreteClientModeManager{id=33409 iface=wlan0 role=ROLE_CLIENT_PRIMARY} ====
Wifi is connected to "guest_5G"
==== ClientModeManager instance: ConcreteClientModeManager{id=82271673 iface=wlan1  role=ROLE_CLIENT_SECONDARY_LONG_LIVED} ====
Wifi is connected to "guest"
  • 1
  • 2
  • 3
  • 4
  • 添加WifiNetworkSuggestion网络连接:adb shell cmd wifi add-suggestion guest_5G wpa3 12345678 -p
  • 执行网络扫描:adb shell cmd wifi start-scan
  • 断开移除WifiNetworkSuggestion网络:adb shell cmd wifi remove-suggestion guest_5G

2.1 adb shell cmd wifi add-suggestion guest_5G wpa3 12345678 -p

添加WifiNetworkSuggestion网络连接:

  1. 参数guest_5G wpa3 12345678 网络名称、类型、密码
  2. 参数-p(或-o)设置 setOemPaid(true)setOemPrivate(true)
    (设备能够连接到副Wi-Fi网络:添加 Wi-Fi 网络建议,方法是将 setOemPaid 或 setOemPrivate 设置为 true。)
  3. mConnectivityManager.requestNetwork(networkRequest, networkCallback)TRANSPORT_WIFI网络请求
    (在 ConnectivityManager 中,提交具有相应功能的 NetworkRequest:为 setOemPaid 提交 NET_CAPABILITY_OEM_PAID 功能(为 setOemPrivate 提交 NET_CAPABILITY_OEM_PRIVATE 功能))
case "add-suggestion": {
    WifiNetworkSuggestion suggestion = buildSuggestion(pw);
    if (suggestion  == null) {
        pw.println("Invalid network suggestion parameter");
        return -1;
    }
    int errorCode = mWifiService.addNetworkSuggestions(
            Arrays.asList(suggestion), SHELL_PACKAGE_NAME, null);
    if (errorCode != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
        pw.println("Add network suggestion failed with error code: " + errorCode);
        return -1;
    }
    // untrusted/oem-paid networks need a corresponding NetworkRequest.
    if (suggestion.isUntrusted()
            || (SdkLevel.isAtLeastS()
            && (suggestion.isOemPaid() || suggestion.isOemPrivate()))) {
        NetworkRequest.Builder networkRequestBuilder =
                new NetworkRequest.Builder()
                        .addTransportType(TRANSPORT_WIFI);
        if (suggestion.isUntrusted()) {
            networkRequestBuilder.removeCapability(NET_CAPABILITY_TRUSTED);
        }
        if (SdkLevel.isAtLeastS()) {
            if (suggestion.isOemPaid()) {
                networkRequestBuilder.addCapability(NET_CAPABILITY_OEM_PAID);
            }
            if (suggestion.isOemPrivate()) {
                networkRequestBuilder.addCapability(NET_CAPABILITY_OEM_PRIVATE);
            }
        }
        NetworkRequest networkRequest = networkRequestBuilder.build();
        ConnectivityManager.NetworkCallback networkCallback =
                new ConnectivityManager.NetworkCallback();
        pw.println("Adding request: " + networkRequest);
        mConnectivityManager.requestNetwork(networkRequest, networkCallback);
        sActiveRequests.put(
                suggestion.getSsid(), Pair.create(networkRequest, networkCallback));
    }
    return 0;
}

//解析网络参数
    private WifiNetworkSuggestion buildSuggestion(PrintWriter pw) {
        String ssid = getNextArgRequired();
        String type = getNextArgRequired();
        WifiNetworkSuggestion.Builder suggestionBuilder =
                new WifiNetworkSuggestion.Builder();
        suggestionBuilder.setSsid(ssid);
        if (TextUtils.equals(type, "wpa3")) {
            suggestionBuilder.setWpa3Passphrase(getNextArgRequired());
        } else if (TextUtils.equals(type, "wpa2")) {
            suggestionBuilder.setWpa2Passphrase(getNextArgRequired());
        } else if (TextUtils.equals(type, "owe")) {
            suggestionBuilder.setIsEnhancedOpen(true);
        } else if (TextUtils.equals(type, "open")) {
            // nothing to do.
        } else {
            throw new IllegalArgumentException("Unknown network type " + type);
        }
        boolean isCarrierMerged = false;
        String option = getNextOption();
        while (option != null) {
            if (option.equals("-u")) {
                suggestionBuilder.setUntrusted(true);
            } else if (option.equals("-o")) {
                if (SdkLevel.isAtLeastS()) {
                    suggestionBuilder.setOemPaid(true);
                } else {
                    throw new IllegalArgumentException(
                            "-o OEM paid suggestions not supported before S");
                }
            } else if (option.equals("-p")) {
                if (SdkLevel.isAtLeastS()) {
                    suggestionBuilder.setOemPrivate(true);
                } else {
                    throw new IllegalArgumentException(
                            "-p OEM private suggestions not supported before S");
                }
            } else if (option.equals("-m")) {
                suggestionBuilder.setIsMetered(true);
            } else if (option.equals("-s")) {
                suggestionBuilder.setCredentialSharedWithUser(true);
            } else if (option.equals("-d")) {
                suggestionBuilder.setIsInitialAutojoinEnabled(false);
            } else if (option.equals("-b")) {
                suggestionBuilder.setBssid(MacAddress.fromString(getNextArgRequired()));
            } else if (option.equals("-r")) {
                if (SdkLevel.isAtLeastS()) {
                    suggestionBuilder.setMacRandomizationSetting(
                            WifiNetworkSuggestion.RANDOMIZATION_NON_PERSISTENT);
                } else {
                    throw new IllegalArgumentException(
                            "-r non_persistent MAC randomization not supported before S");
                }
            } else if (option.equals("-a")) {
                if (SdkLevel.isAtLeastS()) {
                    isCarrierMerged = true;
                } else {
                    throw new IllegalArgumentException("-a option is not supported before S");
                }
            } else if (option.equals("-i")) {
                if (SdkLevel.isAtLeastS()) {
                    int subId = Integer.parseInt(getNextArgRequired());
                    suggestionBuilder.setSubscriptionId(subId);
                } else {
                    throw new IllegalArgumentException(
                            "-i subscription ID option is not supported before S");
                }
            } else if (option.equals("-c")) {
                int carrierId = Integer.parseInt(getNextArgRequired());
                suggestionBuilder.setCarrierId(carrierId);
            } else if (option.equals("-h")) {
                suggestionBuilder.setIsHiddenSsid(true);
            } else {
                pw.println("Ignoring unknown option " + option);
            }
            option = getNextOption();
        }
        WifiNetworkSuggestion suggestion = suggestionBuilder.build();
        if (isCarrierMerged) {
            if (suggestion.wifiConfiguration.subscriptionId
                    == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
                pw.println("Carrier merged network must have valid subscription Id");
                return null;
            }
            suggestion.wifiConfiguration.carrierMerged = true;
        }
        return suggestion;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129

2.2 adb shell cmd wifi remove-suggestion guest_5G

断开移除WifiNetworkSuggestion网络:

  1. mConnectivityManager.unregisterNetworkCallback(nrAndNc.second):移除请求时的NetworkCallback就可以断开WiFi网络
  2. mWifiService.removeNetworkSuggestions():移除WifiNetworkSuggestion网路信息,这里就会移除WifiConfigStoreNetworkSuggestions.xml保存信息
case "remove-suggestion": {
    String ssid = getNextArgRequired();
    String action = getNextArg();
    int actionCode = ACTION_REMOVE_SUGGESTION_DISCONNECT;
    if (action != null && action.equals("lingering")) {
        actionCode = ACTION_REMOVE_SUGGESTION_LINGER;
    }
    List<WifiNetworkSuggestion> suggestions =
            mWifiService.getNetworkSuggestions(SHELL_PACKAGE_NAME);
    WifiNetworkSuggestion suggestion = suggestions.stream()
            .filter(s -> s.getSsid().equals(ssid))
            .findAny()
            .orElse(null);
    if (suggestion == null) {
        pw.println("No matching suggestion to remove");
        return -1;
    }
    mWifiService.removeNetworkSuggestions(
            Arrays.asList(suggestion), SHELL_PACKAGE_NAME, actionCode);
    // untrusted/oem-paid networks need a corresponding NetworkRequest.
    if (suggestion.isUntrusted()
            || (SdkLevel.isAtLeastS()
            && (suggestion.isOemPaid() || suggestion.isOemPrivate()))) {
        Pair<NetworkRequest, ConnectivityManager.NetworkCallback> nrAndNc =
                sActiveRequests.remove(suggestion.getSsid());
        if (nrAndNc == null) {
            pw.println("No matching request to remove");
            return -1;
        }
        pw.println("Removing request: " + nrAndNc.first);
        mConnectivityManager.unregisterNetworkCallback(nrAndNc.second);
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

2.3 查看dumpsys wifi信息WifiConfigStore

packages/modules/Wifi/service/java/com/android/server/wifi/WifiConfigStore.java
packages/modules/Wifi/service/java/com/android/server/wifi/WifiConfigManager.java
packages/modules/Wifi/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java

Dump of WifiConfigStore
WifiConfigStore - Store File Begin ----
Name: /data/misc/apexdata/com.android.wifi/WifiConfigStore.xml, File Id: 0, Credentials encrypted: false
Name: /data/misc/apexdata/com.android.wifi/WifiConfigStoreSoftAp.xml, File Id: 1, Credentials encrypted: false
Name: /data/misc_ce/0/apexdata/com.android.wifi/WifiConfigStore.xml, File Id: 2, Credentials encrypted: false
Name: /data/misc_ce/0/apexdata/com.android.wifi/WifiConfigStoreNetworkSuggestions.xml, File Id: 3, Credentials encrypted: false
WifiConfigStore - Store Data Begin ----
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

3、STA双WiFi连接流程

3.1 STA双WiFi请求前准备工作

  1. 设置setOemPaidsetOemPrivate,并mWifiService.addNetworkSuggestions 添加WifiNetworkSuggestion信息
  2. NetworkRequest请求信息添加TRANSPORT_WIFINET_CAPABILITY_OEM_PRIVATE(或NET_CAPABILITY_OEM_PAID
  3. mConnectivityManager.requestNetwork(networkRequest, networkCallback) 请网络,networkCallback监听连接状态(断开是注销networkCallback
  4. 请求执行到OemWifiNetworkFactory.java#needNetworkForOemPaidWifiNetworkFactory有挂起的网络请求触发,设置mOemPaidConnectionAllowed、mOemPaidConnectionRequestorWs,并开启自动联接setAutoJoinEnabled和启动连接性扫描startConnectivityScan

packages/modules/Wifi/service/java/com/android/server/wifi/OemWifiNetworkFactory.java

protected void needNetworkFor(NetworkRequest networkRequest) {
    if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID)) {
        mOemPaidConnectionReqCount++;
        if (mOemPaidConnectionReqCount == 1) {
            mWifiConnectivityManager.setOemPaidConnectionAllowed(
                    true, new WorkSource(networkRequest.getRequestorUid(),
                            networkRequest.getRequestorPackageName()));
        }
    }
    if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE)) {
        mOemPrivateConnectionReqCount++;
        if (mOemPrivateConnectionReqCount == 1) {
            mWifiConnectivityManager.setOemPrivateConnectionAllowed(
                    true, new WorkSource(networkRequest.getRequestorUid(),
                            networkRequest.getRequestorPackageName()));
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

packages/modules/Wifi/service/java/com/android/server/wifi/WifiConnectivityManager.java

public void setOemPaidConnectionAllowed(boolean allowed, WorkSource requestorWs) {
    localLog("setOemPaidConnectionAllowed: allowed=" + allowed + ", requestorWs="
            + requestorWs);

    if (mOemPaidConnectionAllowed != allowed) {
        mOemPaidConnectionAllowed = allowed;
        mOemPaidConnectionRequestorWs = requestorWs;
        checkAllStatesAndEnableAutoJoin();
    }
}

private void checkAllStatesAndEnableAutoJoin() {
    // if auto-join was disabled externally, don't re-enable for any triggers.
    // External triggers to disable always trumps any internal state.
    setAutoJoinEnabled(mAutoJoinEnabledExternal
            && (mUntrustedConnectionAllowed || mOemPaidConnectionAllowed
            || mOemPrivateConnectionAllowed || mTrustedConnectionAllowed
            || mRestrictedConnectionAllowedUids.size() != 0 || hasMultiInternetConnection())
            && !mSpecificNetworkRequestInProgress);
    startConnectivityScan(SCAN_IMMEDIATELY);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

3.2 STA双WiFi连接时序图

接收到WifiScanner扫描结果AllSingleScanListener#onResults

  1. 获取Wifi候选者 mNetworkSelector.getCandidatesFromScan()
  2. 当支持STA双WIFI连接且 secondaryCmmCandidates不为空,执行handleCandidatesFromScanResultsUsingSecondaryCmmIfAvailablemActiveModeWarden.requestSecondaryLongLivedClientModeManager请求创建副WiFi类型ROLE_CLIENT_SECONDARY_LONG_LIVEDConcreteClientModeManager
  3. 最后执行 connectToNetworkUsingCmmWithoutMbb > triggerConnectToNetworkUsingCmm > clientModeManager.startConnectToNetwork() 连接网络,只有就可主Wifi连接一样,只是不同的wlan0wlan1。(Android WiFi 连接

在这里插入图片描述

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

闽ICP备14008679号