(一百四十八)Android P wifi启动过程中的sta interface创建

1.启动流程回顾

之前在(一百二十八)Android P WIFI启动流程梳理 梳理了WiFi的启动流程,其中有个环节是和interface创建相关的,扒一下具体流程。

(一百四十八)Android P wifi启动过程中的sta interface创建_第1张图片

 

2.流程分析

(一百四十八)Android P wifi启动过程中的sta interface创建_第2张图片

主要看下HalDeviceManager中的相关sta iface创建流程

    /**
     * Create a STA interface if possible. Changes chip mode and removes conflicting interfaces if
     * needed and permitted by priority.
     *
     * @param lowPrioritySta Indicates whether the requested STA is a low priority STA. The priority
     *                       and preemption rules for low priority STA are:
     *                       - Do not destroy any interface for it (even another low priority STA)
     *                       - Destroy it for any other request
     * @param destroyedListener Optional (nullable) listener to call when the allocated interface
     *                          is removed. Will only be registered and used if an interface is
     *                          created successfully.
     * @param handler Handler on which to dispatch listener. Null implies the listener will be
     *                invoked synchronously from the context of the client which triggered the
     *                iface destruction.
     * @return A newly created interface - or null if the interface could not be created.
     */
    public IWifiStaIface createStaIface(boolean lowPrioritySta,
            @Nullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler) {
        return (IWifiStaIface) createIface(IfaceType.STA, lowPrioritySta, destroyedListener,
                handler);
    }

这边api描述的很精炼

  • Create a STA interface if possible.
  • Changes chip mode
  • removes conflicting interfaces if needed and permitted by priority.

 

    private IWifiIface createIface(int ifaceType, boolean lowPriority,
            InterfaceDestroyedListener destroyedListener, Handler handler) {
        if (mDbg) {
            Log.d(TAG, "createIface: ifaceType=" + ifaceType + ", lowPriority=" + lowPriority);
        }

        synchronized (mLock) {
            WifiChipInfo[] chipInfos = getAllChipInfo();
            if (chipInfos == null) {
                Log.e(TAG, "createIface: no chip info found");
                stopWifi(); // major error: shutting down
                return null;
            }

            if (!validateInterfaceCache(chipInfos)) {
                Log.e(TAG, "createIface: local cache is invalid!");
                stopWifi(); // major error: shutting down
                return null;
            }

            IWifiIface iface = createIfaceIfPossible(chipInfos, ifaceType, lowPriority,
                    destroyedListener, handler);
            if (iface != null) { // means that some configuration has changed
                if (!dispatchAvailableForRequestListeners()) {
                    return null; // catastrophic failure - shut down
                }
            }

            return iface;
        }
    }

 

2.1 getAllChipInfo

    /**
     * Get current information about all the chips in the system: modes, current mode (if any), and
     * any existing interfaces.
     *
     * Intended to be called whenever we need to configure the chips - information is NOT cached (to
     * reduce the likelihood that we get out-of-sync).
     */
    private WifiChipInfo[] getAllChipInfo() {
        if (VDBG) Log.d(TAG, "getAllChipInfo");

        synchronized (mLock) {
            if (mWifi == null) {
                Log.e(TAG, "getAllChipInfo: called but mWifi is null!?");
                return null;
            }

            try {
                MutableBoolean statusOk = new MutableBoolean(false);
                Mutable> chipIdsResp = new Mutable<>();

                // get all chip IDs
                mWifi.getChipIds((WifiStatus status, ArrayList chipIds) -> {
                    statusOk.value = status.code == WifiStatusCode.SUCCESS;
                    if (statusOk.value) {
                        chipIdsResp.value = chipIds;
                    } else {
                        Log.e(TAG, "getChipIds failed: " + statusString(status));
                    }
                });
                if (!statusOk.value) {
                    return null;
                }

                if (VDBG) Log.d(TAG, "getChipIds=" + chipIdsResp.value);
                if (chipIdsResp.value.size() == 0) {
                    Log.e(TAG, "Should have at least 1 chip!");
                    return null;
                }

                int chipInfoIndex = 0;
                WifiChipInfo[] chipsInfo = new WifiChipInfo[chipIdsResp.value.size()];

                Mutable chipResp = new Mutable<>();
                for (Integer chipId: chipIdsResp.value) {
                    mWifi.getChip(chipId, (WifiStatus status, IWifiChip chip) -> {
                        statusOk.value = status.code == WifiStatusCode.SUCCESS;
                        if (statusOk.value) {
                            chipResp.value = chip;
                        } else {
                            Log.e(TAG, "getChip failed: " + statusString(status));
                        }
                    });
                    if (!statusOk.value) {
                        return null;
                    }

                    Mutable> availableModesResp = new Mutable<>();
                    chipResp.value.getAvailableModes(
                            (WifiStatus status, ArrayList modes) -> {
                                statusOk.value = status.code == WifiStatusCode.SUCCESS;
                                if (statusOk.value) {
                                    availableModesResp.value = modes;
                                } else {
                                    Log.e(TAG, "getAvailableModes failed: " + statusString(status));
                                }
                            });
                    if (!statusOk.value) {
                        return null;
                    }

                    MutableBoolean currentModeValidResp = new MutableBoolean(false);
                    MutableInt currentModeResp = new MutableInt(0);
                    chipResp.value.getMode((WifiStatus status, int modeId) -> {
                        statusOk.value = status.code == WifiStatusCode.SUCCESS;
                        if (statusOk.value) {
                            currentModeValidResp.value = true;
                            currentModeResp.value = modeId;
                        } else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) {
                            statusOk.value = true; // valid response
                        } else {
                            Log.e(TAG, "getMode failed: " + statusString(status));
                        }
                    });
                    if (!statusOk.value) {
                        return null;
                    }

                    Mutable> ifaceNamesResp = new Mutable<>();
                    MutableInt ifaceIndex = new MutableInt(0);

                    chipResp.value.getStaIfaceNames(
                            (WifiStatus status, ArrayList ifnames) -> {
                                statusOk.value = status.code == WifiStatusCode.SUCCESS;
                                if (statusOk.value) {
                                    ifaceNamesResp.value = ifnames;
                                } else {
                                    Log.e(TAG, "getStaIfaceNames failed: " + statusString(status));
                                }
                            });
                    if (!statusOk.value) {
                        return null;
                    }

                    WifiIfaceInfo[] staIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()];
                    for (String ifaceName: ifaceNamesResp.value) {
                        chipResp.value.getStaIface(ifaceName,
                                (WifiStatus status, IWifiStaIface iface) -> {
                                    statusOk.value = status.code == WifiStatusCode.SUCCESS;
                                    if (statusOk.value) {
                                        WifiIfaceInfo ifaceInfo = new WifiIfaceInfo();
                                        ifaceInfo.name = ifaceName;
                                        ifaceInfo.iface = iface;
                                        staIfaces[ifaceIndex.value++] = ifaceInfo;
                                    } else {
                                        Log.e(TAG, "getStaIface failed: " + statusString(status));
                                    }
                                });
                        if (!statusOk.value) {
                            return null;
                        }
                    }

                    ifaceIndex.value = 0;
                    chipResp.value.getApIfaceNames(
                            (WifiStatus status, ArrayList ifnames) -> {
                                statusOk.value = status.code == WifiStatusCode.SUCCESS;
                                if (statusOk.value) {
                                    ifaceNamesResp.value = ifnames;
                                } else {
                                    Log.e(TAG, "getApIfaceNames failed: " + statusString(status));
                                }
                            });
                    if (!statusOk.value) {
                        return null;
                    }

                    WifiIfaceInfo[] apIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()];
                    for (String ifaceName: ifaceNamesResp.value) {
                        chipResp.value.getApIface(ifaceName,
                                (WifiStatus status, IWifiApIface iface) -> {
                                    statusOk.value = status.code == WifiStatusCode.SUCCESS;
                                    if (statusOk.value) {
                                        WifiIfaceInfo ifaceInfo = new WifiIfaceInfo();
                                        ifaceInfo.name = ifaceName;
                                        ifaceInfo.iface = iface;
                                        apIfaces[ifaceIndex.value++] = ifaceInfo;
                                    } else {
                                        Log.e(TAG, "getApIface failed: " + statusString(status));
                                    }
                                });
                        if (!statusOk.value) {
                            return null;
                        }
                    }

                    ifaceIndex.value = 0;
                    chipResp.value.getP2pIfaceNames(
                            (WifiStatus status, ArrayList ifnames) -> {
                                statusOk.value = status.code == WifiStatusCode.SUCCESS;
                                if (statusOk.value) {
                                    ifaceNamesResp.value = ifnames;
                                } else {
                                    Log.e(TAG, "getP2pIfaceNames failed: " + statusString(status));
                                }
                            });
                    if (!statusOk.value) {
                        return null;
                    }

                    WifiIfaceInfo[] p2pIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()];
                    for (String ifaceName: ifaceNamesResp.value) {
                        chipResp.value.getP2pIface(ifaceName,
                                (WifiStatus status, IWifiP2pIface iface) -> {
                                    statusOk.value = status.code == WifiStatusCode.SUCCESS;
                                    if (statusOk.value) {
                                        WifiIfaceInfo ifaceInfo = new WifiIfaceInfo();
                                        ifaceInfo.name = ifaceName;
                                        ifaceInfo.iface = iface;
                                        p2pIfaces[ifaceIndex.value++] = ifaceInfo;
                                    } else {
                                        Log.e(TAG, "getP2pIface failed: " + statusString(status));
                                    }
                                });
                        if (!statusOk.value) {
                            return null;
                        }
                    }

                    ifaceIndex.value = 0;
                    chipResp.value.getNanIfaceNames(
                            (WifiStatus status, ArrayList ifnames) -> {
                                statusOk.value = status.code == WifiStatusCode.SUCCESS;
                                if (statusOk.value) {
                                    ifaceNamesResp.value = ifnames;
                                } else {
                                    Log.e(TAG, "getNanIfaceNames failed: " + statusString(status));
                                }
                            });
                    if (!statusOk.value) {
                        return null;
                    }

                    WifiIfaceInfo[] nanIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()];
                    for (String ifaceName: ifaceNamesResp.value) {
                        chipResp.value.getNanIface(ifaceName,
                                (WifiStatus status, IWifiNanIface iface) -> {
                                    statusOk.value = status.code == WifiStatusCode.SUCCESS;
                                    if (statusOk.value) {
                                        WifiIfaceInfo ifaceInfo = new WifiIfaceInfo();
                                        ifaceInfo.name = ifaceName;
                                        ifaceInfo.iface = iface;
                                        nanIfaces[ifaceIndex.value++] = ifaceInfo;
                                    } else {
                                        Log.e(TAG, "getNanIface failed: " + statusString(status));
                                    }
                                });
                        if (!statusOk.value) {
                            return null;
                        }
                    }

                    WifiChipInfo chipInfo = new WifiChipInfo();
                    chipsInfo[chipInfoIndex++] = chipInfo;

                    chipInfo.chip = chipResp.value;
                    chipInfo.chipId = chipId;
                    chipInfo.availableModes = availableModesResp.value;
                    chipInfo.currentModeIdValid = currentModeValidResp.value;
                    chipInfo.currentModeId = currentModeResp.value;
                    chipInfo.ifaces[IfaceType.STA] = staIfaces;
                    chipInfo.ifaces[IfaceType.AP] = apIfaces;
                    chipInfo.ifaces[IfaceType.P2P] = p2pIfaces;
                    chipInfo.ifaces[IfaceType.NAN] = nanIfaces;
                }

                return chipsInfo;
            } catch (RemoteException e) {
                Log.e(TAG, "getAllChipInfoAndValidateCache exception: " + e);
            }
        }

        return null;
    }

顾名思义,获取芯片相关信息

                    WifiChipInfo chipInfo = new WifiChipInfo();
                    chipsInfo[chipInfoIndex++] = chipInfo;

                    chipInfo.chip = chipResp.value;
                    chipInfo.chipId = chipId;
                    chipInfo.availableModes = availableModesResp.value;
                    chipInfo.currentModeIdValid = currentModeValidResp.value;
                    chipInfo.currentModeId = currentModeResp.value;
                    chipInfo.ifaces[IfaceType.STA] = staIfaces;
                    chipInfo.ifaces[IfaceType.AP] = apIfaces;
                    chipInfo.ifaces[IfaceType.P2P] = p2pIfaces;
                    chipInfo.ifaces[IfaceType.NAN] = nanIfaces;

可以先看最后,将从底层获取上来的信息封装成了一个java对象,WifiChipInfo.

那在往上看下WifiChipInfo 各个参数是如何获取的

http://androidxref.com/9.0.0_r3/xref/hardware/interfaces/wifi/1.0/IWifiChip.hal#108

/**
 * Interface that represents a chip that must be configured as a single unit.
 * The HAL/driver/firmware will be responsible for determining which phy is used
 * to perform operations like NAN, RTT, etc.
 */
interface IWifiChip {
  /**
   * Set of interface types with the maximum number of interfaces that can have
   * one of the specified type for a given ChipIfaceCombination. See
   * ChipIfaceCombination for examples.
   */
  struct ChipIfaceCombinationLimit {
    vec types; // Each IfaceType must occur at most once.
    uint32_t maxIfaces;
  };

  /**
   * Set of interfaces that can operate concurrently when in a given mode. See
   * ChipMode below.
   *
   * For example:
   *   [{STA} <= 2]
   *       At most two STA interfaces are supported
   *       [], [STA], [STA+STA]
   *
   *   [{STA} <= 1, {NAN} <= 1, {AP} <= 1]
   *       Any combination of STA, NAN, AP
   *       [], [STA], [NAN], [AP], [STA+NAN], [STA+AP], [NAN+AP], [STA+NAN+AP]
   *
   *   [{STA} <= 1, {NAN,P2P} <= 1]
   *       Optionally a STA and either NAN or P2P
   *       [], [STA], [STA+NAN], [STA+P2P], [NAN], [P2P]
   *       Not included [NAN+P2P], [STA+NAN+P2P]
   *
   *   [{STA} <= 1, {STA,NAN} <= 1]
   *       Optionally a STA and either a second STA or a NAN
   *       [], [STA], [STA+NAN], [STA+STA], [NAN]
   *       Not included [STA+STA+NAN]
   */
  struct ChipIfaceCombination {
    vec limits;
  };

  /**
   * A mode that the chip can be put in. A mode defines a set of constraints on
   * the interfaces that can exist while in that mode. Modes define a unit of
   * configuration where all interfaces must be torn down to switch to a
   * different mode. Some HALs may only have a single mode, but an example where
   * multiple modes would be required is if a chip has different firmwares with
   * different capabilities.
   *
   * When in a mode, it must be possible to perform any combination of creating
   * and removing interfaces as long as at least one of the
   * ChipIfaceCombinations is satisfied. This means that if a chip has two
   * available combinations, [{STA} <= 1] and [{AP} <= 1] then it is expected
   * that exactly one STA interface or one AP interface can be created, but it
   * is not expected that both a STA and AP interface could be created. If it
   * was then there would be a single available combination
   * [{STA} <=1, {AP} <= 1].
   *
   * When switching between two available combinations it is expected that
   * interfaces only supported by the initial combination must be removed until
   * the target combination is also satisfied. At that point new interfaces
   * satisfying only the target combination can be added (meaning the initial
   * combination limits will no longer satisfied). The addition of these new
   * interfaces must not impact the existence of interfaces that satisfy both
   * combinations.
   *
   * For example, a chip with available combinations:
   *     [{STA} <= 2, {NAN} <=1] and [{STA} <=1, {NAN} <= 1, {AP} <= 1}]
   * If the chip currently has 3 interfaces STA, STA and NAN and wants to add an
   * AP interface in place of one of the STAs then first one of the STA
   * interfaces must be removed and then the AP interface can be created after
   * the STA had been torn down. During this process the remaining STA and NAN
   * interfaces must not be removed/recreated.
   *
   * If a chip does not support this kind of reconfiguration in this mode then
   * the combinations must be separated into two separate modes. Before
   * switching modes all interfaces must be torn down, the mode switch must be
   * enacted and when it completes the new interfaces must be brought up.
   */
  struct ChipMode {
    /**
     * Id that can be used to put the chip in this mode.
     */
    ChipModeId id;

    /**
     * A list of the possible interface combinations that the chip can have
     * while in this mode.
     */
    vec availableCombinations;
  };

 

 

2.1.1 chipIDs

                MutableBoolean statusOk = new MutableBoolean(false);
                Mutable> chipIdsResp = new Mutable<>();

                // get all chip IDs
                mWifi.getChipIds((WifiStatus status, ArrayList chipIds) -> {
                    statusOk.value = status.code == WifiStatusCode.SUCCESS;
                    if (statusOk.value) {
                        chipIdsResp.value = chipIds;
                    } else {
                        Log.e(TAG, "getChipIds failed: " + statusString(status));
                    }
                });

PS:Mutable是可变的意思,https://blog.csdn.net/rentee/article/details/82999955 中有讲,后续再看下

 

hardware/interfaces/wifi/1.2/default/wifi.cpp

Return Wifi::getChipIds(getChipIds_cb hidl_status_cb) {
    return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
                           &Wifi::getChipIdsInternal, hidl_status_cb);
}

std::pair> Wifi::getChipIdsInternal() {
    std::vector chip_ids;
    if (chip_.get()) {
        chip_ids.emplace_back(kChipId);
    }
    return {createWifiStatus(WifiStatusCode::SUCCESS), std::move(chip_ids)};
}

namespace {
// Chip ID to use for the only supported chip.
static constexpr android::hardware::wifi::V1_0::ChipId kChipId = 0;
}  // namespace

从代码来看Android原生默认芯片个数为1,id = 0

 

2.1.2 chip

Mutable chipResp = new Mutable<>();
                for (Integer chipId: chipIdsResp.value) {
                    mWifi.getChip(chipId, (WifiStatus status, IWifiChip chip) -> {
                        statusOk.value = status.code == WifiStatusCode.SUCCESS;
                        if (statusOk.value) {
                            chipResp.value = chip;
                        } else {
                            Log.e(TAG, "getChip failed: " + statusString(status));
                        }
                    });
                    if (!statusOk.value) {
                        return null;
                    }

hardware/interfaces/wifi/1.2/default/wifi.cpp

Return Wifi::getChip(ChipId chip_id, getChip_cb hidl_status_cb) {
    return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
                           &Wifi::getChipInternal, hidl_status_cb, chip_id);
}


std::pair> Wifi::getChipInternal(ChipId chip_id) {
    if (!chip_.get()) {
        return {createWifiStatus(WifiStatusCode::ERROR_NOT_STARTED), nullptr};
    }
    if (chip_id != kChipId) {
        return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
    }
    return {createWifiStatus(WifiStatusCode::SUCCESS), chip_};
}

而chip_是之前加载驱动成功后初始化起来的,如注释所示: // Create the chip instance once the HAL is started.

WifiStatus Wifi::startInternal() {
    if (run_state_ == RunState::STARTED) {
        return createWifiStatus(WifiStatusCode::SUCCESS);
    } else if (run_state_ == RunState::STOPPING) {
        return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
                                "HAL is stopping");
    }
    WifiStatus wifi_status = initializeModeControllerAndLegacyHal();
    if (wifi_status.code == WifiStatusCode::SUCCESS) {
        // Create the chip instance once the HAL is started.
        chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_,
                             feature_flags_);
        run_state_ = RunState::STARTED;
        for (const auto& callback : event_cb_handler_.getCallbacks()) {
            if (!callback->onStart().isOk()) {
                LOG(ERROR) << "Failed to invoke onStart callback";
            };
        }
        LOG(INFO) << "Wifi HAL started";
    } else {
        for (const auto& callback : event_cb_handler_.getCallbacks()) {
            if (!callback->onFailure(wifi_status).isOk()) {
                LOG(ERROR) << "Failed to invoke onFailure callback";
            }
        }
        LOG(ERROR) << "Wifi HAL start failed";
    }
    return wifi_status;
}

 

2.1.3 AvailableModes

                    Mutable> availableModesResp = new Mutable<>();
                    chipResp.value.getAvailableModes(
                            (WifiStatus status, ArrayList modes) -> {
                                statusOk.value = status.code == WifiStatusCode.SUCCESS;
                                if (statusOk.value) {
                                    availableModesResp.value = modes;
                                } else {
                                    Log.e(TAG, "getAvailableModes failed: " + statusString(status));
                                }
                            });

hardware/interfaces/wifi/1.2/default/wifi_chip.cpp

Return WifiChip::getAvailableModes(getAvailableModes_cb hidl_status_cb) {
    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
                           &WifiChip::getAvailableModesInternal,
                           hidl_status_cb);
}

std::pair>
WifiChip::getAvailableModesInternal() {
    return {createWifiStatus(WifiStatusCode::SUCCESS), modes_};
}

再看下modes_是在哪里初始化的

void WifiChip::populateModes() {
    // The chip combination supported for current devices is fixed.
    // They can be one of the following based on device features:
    // a) 2 separate modes of operation with 1 interface combination each:
    //    Mode 1 (STA mode): Will support 1 STA and 1 P2P or NAN(optional)
    //                       concurrent iface operations.
    //    Mode 2 (AP mode): Will support 1 AP iface operation.
    //
    // b) 1 mode of operation with 2 interface combinations
    // (conditional on isDualInterfaceSupported()):
    //    Interface Combination 1: Will support 1 STA and 1 P2P or NAN(optional)
    //                             concurrent iface operations.
    //    Interface Combination 2: Will support 1 STA and 1 AP concurrent
    //                             iface operations.
    // If Aware is enabled (conditional on isAwareSupported()), the iface
    // combination will be modified to support either P2P or NAN in place of
    // just P2P.
    if (feature_flags_.lock()->isDualInterfaceSupported()) {
        // V2 Iface combinations for Mode Id = 2.
        const IWifiChip::ChipIfaceCombinationLimit
            chip_iface_combination_limit_1 = {{IfaceType::STA}, 1};
        const IWifiChip::ChipIfaceCombinationLimit
            chip_iface_combination_limit_2 = {{IfaceType::AP}, 1};
        IWifiChip::ChipIfaceCombinationLimit chip_iface_combination_limit_3;
        if (feature_flags_.lock()->isAwareSupported()) {
            chip_iface_combination_limit_3 = {{IfaceType::P2P, IfaceType::NAN},
                                              1};
        } else {
            chip_iface_combination_limit_3 = {{IfaceType::P2P}, 1};
        }
        const IWifiChip::ChipIfaceCombination chip_iface_combination_1 = {
            {chip_iface_combination_limit_1, chip_iface_combination_limit_2}};
        const IWifiChip::ChipIfaceCombination chip_iface_combination_2 = {
            {chip_iface_combination_limit_1, chip_iface_combination_limit_3}};
        if (feature_flags_.lock()->isApDisabled()) {
          const IWifiChip::ChipMode chip_mode = {
              kV2ChipModeId,
              {chip_iface_combination_2}};
          modes_ = {chip_mode};
        } else {
          const IWifiChip::ChipMode chip_mode = {
            kV2ChipModeId,
            {chip_iface_combination_1, chip_iface_combination_2}};
          modes_ = {chip_mode};
        }
    } else {
        // V1 Iface combinations for Mode Id = 0. (STA Mode)
        const IWifiChip::ChipIfaceCombinationLimit
            sta_chip_iface_combination_limit_1 = {{IfaceType::STA}, 1};
        IWifiChip::ChipIfaceCombinationLimit sta_chip_iface_combination_limit_2;
        if (feature_flags_.lock()->isAwareSupported()) {
            sta_chip_iface_combination_limit_2 = {
                {IfaceType::P2P, IfaceType::NAN}, 1};
        } else {
            sta_chip_iface_combination_limit_2 = {{IfaceType::P2P}, 1};
        }
        const IWifiChip::ChipIfaceCombination sta_chip_iface_combination = {
            {sta_chip_iface_combination_limit_1,
             sta_chip_iface_combination_limit_2}};
        const IWifiChip::ChipMode sta_chip_mode = {
            kV1StaChipModeId, {sta_chip_iface_combination}};
        // Iface combinations for Mode Id = 1. (AP Mode)
        const IWifiChip::ChipIfaceCombinationLimit
            ap_chip_iface_combination_limit = {{IfaceType::AP}, 1};
        const IWifiChip::ChipIfaceCombination ap_chip_iface_combination = {
            {ap_chip_iface_combination_limit}};
        const IWifiChip::ChipMode ap_chip_mode = {kV1ApChipModeId,
                                                  {ap_chip_iface_combination}};
        if (feature_flags_.lock()->isApDisabled()) {
          modes_ = {sta_chip_mode};
        } else {
          modes_ = {sta_chip_mode, ap_chip_mode};
        }
    }
}

支持的模式有讲的清楚,先区分是否支持DualInterface

1)若支持

i 支持ap,则组合模式有sta+p2p 或者sta+ap,标记为kV2ChipModeId

ii 不支持ap,则组合模式有sta + p2p,标记为kV2ChipModeId

2)若不支持

i 支持ap,则组合模式有sta+p2p 或者ap,标记为kV1ApChipModeId

ii 不支持ap,则组合模式有sta + p2p,标记为kV1StaChipModeId

//当前设备支持的芯片组合是固定的。
     //它们可以是基于设备功能的以下之一:
     // a)单接口   2种不同的操作模式,每种模式有1个接口组合:
     //模式1(STA模式):支持1个STA和1个P2P或NAN(可选)
     //并发iface操作。
     //模式2(AP模式):支持1个AP操作。
    //
     // b)双接口 具有2个接口组合的1种操作模式
     //(以isDualInterfaceSupported()为条件):
     //接口组合1:支持1个STA和1个P2P或NAN(可选)
     //并发iface操作。
     //接口组合2:将支持1个STA和1个AP并发
     // iface运营
     //如果启用了Aware(以isAwareSupported()为条件),则为iface
     //将修改组合以支持P2P或NAN代替
     //只是P2P。

// These mode ID's should be unique (even across combo versions). Refer to
// handleChipConfiguration() for it's usage.
// Mode ID's for V1
constexpr ChipModeId kV1StaChipModeId = 0;
constexpr ChipModeId kV1ApChipModeId = 1;
// Mode ID for V2
constexpr ChipModeId kV2ChipModeId = 2;

 

2.1.4 currentModeValid & currentMode

                    MutableBoolean currentModeValidResp = new MutableBoolean(false);
                    MutableInt currentModeResp = new MutableInt(0);
                    chipResp.value.getMode((WifiStatus status, int modeId) -> {
                        statusOk.value = status.code == WifiStatusCode.SUCCESS;
                        if (statusOk.value) {
                            currentModeValidResp.value = true;
                            currentModeResp.value = modeId;
                        } else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) {
                            statusOk.value = true; // valid response
                        } else {
                            Log.e(TAG, "getMode failed: " + statusString(status));
                        }
                    });

hardware/interfaces/wifi/1.2/default/wifi_chip.cpp

Return WifiChip::getMode(getMode_cb hidl_status_cb) {
    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
                           &WifiChip::getModeInternal, hidl_status_cb);
}

std::pair WifiChip::getModeInternal() {
    if (!isValidModeId(current_mode_id_)) {
        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE),
                current_mode_id_};
    }
    return {createWifiStatus(WifiStatusCode::SUCCESS), current_mode_id_};
}

看下current_mode_id_是何时初始化的

WifiStatus WifiChip::configureChipInternal(
    /* NONNULL */ std::unique_lock* lock,
    ChipModeId mode_id) {
    if (!isValidModeId(mode_id)) {
        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
    }
    if (mode_id == current_mode_id_) {
        LOG(DEBUG) << "Already in the specified mode " << mode_id;
        return createWifiStatus(WifiStatusCode::SUCCESS);
    }
    WifiStatus status = handleChipConfiguration(lock, mode_id);
    if (status.code != WifiStatusCode::SUCCESS) {
        for (const auto& callback : event_cb_handler_.getCallbacks()) {
            if (!callback->onChipReconfigureFailure(status).isOk()) {
                LOG(ERROR)
                    << "Failed to invoke onChipReconfigureFailure callback";
            }
        }
        return status;
    }
    for (const auto& callback : event_cb_handler_.getCallbacks()) {
        if (!callback->onChipReconfigured(mode_id).isOk()) {
            LOG(ERROR) << "Failed to invoke onChipReconfigured callback";
        }
    }
    current_mode_id_ = mode_id;
    LOG(INFO) << "Configured chip in mode " << mode_id;
    return status;
}

configureChipInternal是后续创建sta iface的时候配置的,初始的时候应该是

current_mode_id_(kInvalidModeId)

 

2.1.5 staIfaceNames & staIface

                    Mutable> ifaceNamesResp = new Mutable<>();
                    MutableInt ifaceIndex = new MutableInt(0);

                    chipResp.value.getStaIfaceNames(
                            (WifiStatus status, ArrayList ifnames) -> {
                                statusOk.value = status.code == WifiStatusCode.SUCCESS;
                                if (statusOk.value) {
                                    ifaceNamesResp.value = ifnames;
                                } else {
                                    Log.e(TAG, "getStaIfaceNames failed: " + statusString(status));
                                }
                            });
                    if (!statusOk.value) {
                        return null;
                    }

                    WifiIfaceInfo[] staIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()];
                    for (String ifaceName: ifaceNamesResp.value) {
                        chipResp.value.getStaIface(ifaceName,
                                (WifiStatus status, IWifiStaIface iface) -> {
                                    statusOk.value = status.code == WifiStatusCode.SUCCESS;
                                    if (statusOk.value) {
                                        WifiIfaceInfo ifaceInfo = new WifiIfaceInfo();
                                        ifaceInfo.name = ifaceName;
                                        ifaceInfo.iface = iface;
                                        staIfaces[ifaceIndex.value++] = ifaceInfo;
                                    } else {
                                        Log.e(TAG, "getStaIface failed: " + statusString(status));
                                    }
                                });
                        if (!statusOk.value) {
                            return null;
                        }
                    }

hardware/interfaces/wifi/1.2/default/wifi_chip.cpp

Return WifiChip::getStaIfaceNames(getStaIfaceNames_cb hidl_status_cb) {
    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
                           &WifiChip::getStaIfaceNamesInternal, hidl_status_cb);
}

std::pair>
WifiChip::getStaIfaceNamesInternal() {
    if (sta_ifaces_.empty()) {
        return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
    }
    return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(sta_ifaces_)};
}

std::pair> WifiChip::createStaIfaceInternal() {
    if (!canCurrentModeSupportIfaceOfType(IfaceType::STA)) {
        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
    }
    std::string ifname = allocateApOrStaIfaceName();
    sp iface = new WifiStaIface(ifname, legacy_hal_);
    sta_ifaces_.push_back(iface);
    for (const auto& callback : event_cb_handler_.getCallbacks()) {
        if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) {
            LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
        }
    }
    return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
}

// Return "wlan0", if "wlan0" is not already in use, else return "wlan1".
// This is based on the assumption that we'll have a max of 2 concurrent
// AP/STA ifaces.
std::string WifiChip::allocateApOrStaIfaceName() {
    auto ap_iface = findUsingName(ap_ifaces_, getWlan0IfaceName());
    auto sta_iface = findUsingName(sta_ifaces_, getWlan0IfaceName());
    if (!ap_iface.get() && !sta_iface.get()) {
        return getWlan0IfaceName();
    }
    ap_iface = findUsingName(ap_ifaces_, getWlan1IfaceName());
    sta_iface = findUsingName(sta_ifaces_, getWlan1IfaceName());
    if (!ap_iface.get() && !sta_iface.get()) {
        return getWlan1IfaceName();
    }
    // This should never happen. We screwed up somewhere if it did.
    CHECK(0) << "wlan0 and wlan1 in use already!";
    return {};
}

可以看到如果wlan0没有用就返回wlan0,否则返回wlan1,否则返回空

 

 

Return WifiChip::getStaIface(const hidl_string& ifname,
                                   getStaIface_cb hidl_status_cb) {
    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
                           &WifiChip::getStaIfaceInternal, hidl_status_cb,
                           ifname);
}

std::pair> WifiChip::getStaIfaceInternal(
    const std::string& ifname) {
    const auto iface = findUsingName(sta_ifaces_, ifname);
    if (!iface.get()) {
        return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
    }
    return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
}

template 
sp findUsingName(std::vector>& ifaces,
                        const std::string& name) {
    std::vector names;
    for (const auto& iface : ifaces) {
        if (name == iface->getName()) {
            return iface;
        }
    }
    return nullptr;
}

用刚才的获取到的接口名称来获取对应的iface

 

2.2 createIfaceIfPossible

    private IWifiIface createIfaceIfPossible(WifiChipInfo[] chipInfos, int ifaceType,
            boolean lowPriority, InterfaceDestroyedListener destroyedListener, Handler handler) {
        if (VDBG) {
            Log.d(TAG, "createIfaceIfPossible: chipInfos=" + Arrays.deepToString(chipInfos)
                    + ", ifaceType=" + ifaceType + ", lowPriority=" + lowPriority);
        }
        synchronized (mLock) {
            IfaceCreationData bestIfaceCreationProposal = null;
            for (WifiChipInfo chipInfo: chipInfos) {
                for (IWifiChip.ChipMode chipMode: chipInfo.availableModes) {
                    for (IWifiChip.ChipIfaceCombination chipIfaceCombo : chipMode
                            .availableCombinations) {
                        int[][] expandedIfaceCombos = expandIfaceCombos(chipIfaceCombo);
                        if (VDBG) {
                            Log.d(TAG, chipIfaceCombo + " expands to "
                                    + Arrays.deepToString(expandedIfaceCombos));
                        }

                        for (int[] expandedIfaceCombo: expandedIfaceCombos) {
                            IfaceCreationData currentProposal = canIfaceComboSupportRequest(
                                    chipInfo, chipMode, expandedIfaceCombo, ifaceType, lowPriority);
                            if (compareIfaceCreationData(currentProposal,
                                    bestIfaceCreationProposal)) {
                                if (VDBG) Log.d(TAG, "new proposal accepted");
                                bestIfaceCreationProposal = currentProposal;
                            }
                        }
                    }
                }
            }

            if (bestIfaceCreationProposal != null) {
                IWifiIface iface = executeChipReconfiguration(bestIfaceCreationProposal, ifaceType);
                if (iface != null) {
                    InterfaceCacheEntry cacheEntry = new InterfaceCacheEntry();

                    cacheEntry.chip = bestIfaceCreationProposal.chipInfo.chip;
                    cacheEntry.chipId = bestIfaceCreationProposal.chipInfo.chipId;
                    cacheEntry.name = getName(iface);
                    cacheEntry.type = ifaceType;
                    if (destroyedListener != null) {
                        cacheEntry.destroyedListeners.add(
                                new InterfaceDestroyedListenerProxy(
                                        cacheEntry.name, destroyedListener, handler));
                    }
                    cacheEntry.creationTime = mClock.getUptimeSinceBootMillis();
                    cacheEntry.isLowPriority = lowPriority;

                    if (mDbg) Log.d(TAG, "createIfaceIfPossible: added cacheEntry=" + cacheEntry);
                    mInterfaceInfoCache.put(
                            Pair.create(cacheEntry.name, cacheEntry.type), cacheEntry);
                    return iface;
                }
            }
        }

        return null;
    }

遍历所有的组合找到最适合的,关键api

  • expandIfaceCombos
  • canIfaceComboSupportRequest
  • compareIfaceCreationData
        synchronized (mLock) {
            IfaceCreationData bestIfaceCreationProposal = null;
            for (WifiChipInfo chipInfo: chipInfos) {
//暂时只有一个芯片信息
                for (IWifiChip.ChipMode chipMode: chipInfo.availableModes) {
//对应于
支持的模式有讲的清楚,先区分是否支持DualInterface

1)若支持

i 支持ap,则模式单一,组合有2种,为sta+p2p 或者sta+ap,标记为kV2ChipModeId

ii 不支持ap,则模式单一,组合有1种,为sta + p2p,标记为kV2ChipModeId

2)若不支持

i 支持ap,则模式有sta+p2p 或者ap,标记为kV1ApChipModeId

ii 不支持ap,则模式单一,为sta+p2p,标记为kV1StaChipModeId


                    for (IWifiChip.ChipIfaceCombination chipIfaceCombo : chipMode
                            .availableCombinations) {
对应不同的模式有不同的combinations
                        int[][] expandedIfaceCombos = expandIfaceCombos(chipIfaceCombo);
                        if (VDBG) {
                            Log.d(TAG, chipIfaceCombo + " expands to "
                                    + Arrays.deepToString(expandedIfaceCombos));
                        }

                        for (int[] expandedIfaceCombo: expandedIfaceCombos) {
                            IfaceCreationData currentProposal = canIfaceComboSupportRequest(
                                    chipInfo, chipMode, expandedIfaceCombo, ifaceType, lowPriority);
                            if (compareIfaceCreationData(currentProposal,
                                    bestIfaceCreationProposal)) {
                                if (VDBG) Log.d(TAG, "new proposal accepted");
                                bestIfaceCreationProposal = currentProposal;
                            }
                        }
                    }
                }
            }

 

2.2.1 expandIfaceCombos

    /**
     * Expands (or provides an alternative representation) of the ChipIfaceCombination as all
     * possible combinations of interface.
     *
     * Returns [# of combinations][4 (IfaceType)]
     *
     * Note: there could be duplicates - allow (inefficient but ...).
     * TODO: optimize by using a Set as opposed to a []: will remove duplicates. Will need to
     * provide correct hashes.
     */
    private int[][] expandIfaceCombos(IWifiChip.ChipIfaceCombination chipIfaceCombo) {
        int numOfCombos = 1;
        for (IWifiChip.ChipIfaceCombinationLimit limit: chipIfaceCombo.limits) {
            for (int i = 0; i < limit.maxIfaces; ++i) {
                numOfCombos *= limit.types.size();
            }
        }

        int[][] expandedIfaceCombos = new int[numOfCombos][IFACE_TYPES_BY_PRIORITY.length];

        int span = numOfCombos; // span of an individual type (or sub-tree size)
        for (IWifiChip.ChipIfaceCombinationLimit limit: chipIfaceCombo.limits) {
            for (int i = 0; i < limit.maxIfaces; ++i) {
                span /= limit.types.size();
                for (int k = 0; k < numOfCombos; ++k) {
                    expandedIfaceCombos[k][limit.types.get((k / span) % limit.types.size())]++;
                }
            }
        }

        return expandedIfaceCombos;
    }

随便看个iface combination

        const IWifiChip::ChipIfaceCombinationLimit
            chip_iface_combination_limit_1 = {{IfaceType::STA}, 1};
        const IWifiChip::ChipIfaceCombinationLimit
            chip_iface_combination_limit_2 = {{IfaceType::AP}, 1};
        const IWifiChip::ChipIfaceCombination chip_iface_combination_1 = {
            {chip_iface_combination_limit_1, chip_iface_combination_limit_2}};

http://androidxref.com/9.0.0_r3/xref/hardware/interfaces/wifi/1.0/IWifiChip.hal#108

  /**
   * Set of interface types with the maximum number of interfaces that can have
   * one of the specified type for a given ChipIfaceCombination. See
   * ChipIfaceCombination for examples.
   */
  struct ChipIfaceCombinationLimit {
    vec types; // Each IfaceType must occur at most once.
    uint32_t maxIfaces;
  };

假定iface combination 为 STA + AP,带入debug

    /**
     * Expands (or provides an alternative representation) of the ChipIfaceCombination as all
     * possible combinations of interface.
     *
     * Returns [# of combinations][4 (IfaceType)]
     *
     * Note: there could be duplicates - allow (inefficient but ...).
     * TODO: optimize by using a Set as opposed to a []: will remove duplicates. Will need to
     * provide correct hashes.
     */
    private int[][] expandIfaceCombos(IWifiChip.ChipIfaceCombination chipIfaceCombo) {
        int numOfCombos = 1;
        for (IWifiChip.ChipIfaceCombinationLimit limit: chipIfaceCombo.limits) {
            for (int i = 0; i < limit.maxIfaces; ++i) {
                numOfCombos *= limit.types.size();
//计算双接口的组合个数 numOfCombos = 1
            }
        }

        int[][] expandedIfaceCombos = new int[numOfCombos][IFACE_TYPES_BY_PRIORITY.length];
//拼接成一个二维数组,行为numOfCombos,1 ,列为4,ap+sta+p2p+NAN
//    /* This "PRIORITY" is not for deciding interface elimination (that is controlled by
     * allowedToDeleteIfaceTypeForRequestedType. This priority is used for:
     * - Comparing 2 configuration options
     * - Order of dispatch of available for request listeners
     */
    private static final int[] IFACE_TYPES_BY_PRIORITY =
            {IfaceType.AP, IfaceType.STA, IfaceType.P2P, IfaceType.NAN};
//
        int span = numOfCombos; // span of an individual type (or sub-tree size)
//span = 1

        for (IWifiChip.ChipIfaceCombinationLimit limit: chipIfaceCombo.limits) {
            for (int i = 0; i < limit.maxIfaces; ++i) {
                span /= limit.types.size();
//span = 1;
                for (int k = 0; k < numOfCombos; ++k) {
                    expandedIfaceCombos[k][limit.types.get((k / span) % limit.types.size())]++;
                }
            }
        }

        return expandedIfaceCombos;
    }

对于numofCombos的计算参考,比如

  /**
   * Set of interfaces that can operate concurrently when in a given mode. See
   * ChipMode below.
   *
   * For example:
   *   [{STA} <= 2]
   *       At most two STA interfaces are supported
   *       [], [STA], [STA+STA]
numofCombos=1
   *
   *   [{STA} <= 1, {NAN} <= 1, {AP} <= 1]
   *       Any combination of STA, NAN, AP
   *       [], [STA], [NAN], [AP], [STA+NAN], [STA+AP], [NAN+AP], [STA+NAN+AP]
   *
numofCombos=1
   *   [{STA} <= 1, {NAN,P2P} <= 1]
   *       Optionally a STA and either NAN or P2P
   *       [], [STA], [STA+NAN], [STA+P2P], [NAN], [P2P]
   *       Not included [NAN+P2P], [STA+NAN+P2P]
   *
numofCombos=2
   *   [{STA} <= 1, {STA,NAN} <= 1]
   *       Optionally a STA and either a second STA or a NAN
   *       [], [STA], [STA+NAN], [STA+STA], [NAN]
   *       Not included [STA+STA+NAN]
   */
numofCombos=2
  struct ChipIfaceCombination {
    vec limits;
  };

画一个二维数组

numofCombos\IFACE_TYPES_BY_PRIORITY 0 1 2 3
0 1 1 0 0

懵逼了,vec是个矢量,get的确实是int值,准确说来是枚举值

/**
 * List of Iface types supported.
 */
enum IfaceType : uint32_t {
  STA,
  AP,
  P2P,
  /**
   * NAN control interface. Datapath support must be queried and created
   * through this interface.
   */
  NAN,
};

最后得到的二位数组是【1,1,0,0】表示啥呢。。。

在举个例子

   *   [{STA} <= 1, {NAN,P2P} <= 1]
   *       Optionally a STA and either NAN or P2P
   *       [], [STA], [STA+NAN], [STA+P2P], [NAN], [P2P]
   *       Not included [NAN+P2P], [STA+NAN+P2P]
   *
numofCombos=2

numofCombos\IFACE_TYPES_BY_PRIORITY 0 1 2 3
0 1     1
1 1   1  

        for (IWifiChip.ChipIfaceCombinationLimit limit: chipIfaceCombo.limits) {
            for (int i = 0; i < limit.maxIfaces; ++i) {
                span /= limit.types.size(); 1
                for (int k = 0; k < numOfCombos; ++k) {
                    expandedIfaceCombos[k][limit.types.get((k / span) % limit.types.size())]++;
                }
            }
        }

虽然算法不是很理解,但是从表来看是将combo用二维数组表示了下。待续。。。

 

2.2.2 canIfaceComboSupportRequest

    /**
     * Checks whether the input chip-iface-combo can support the requested interface type: if not
     * then returns null, if yes then returns information containing the list of interfaces which
     * would have to be removed first before the requested interface can be created.
     *
     * Note: the list of interfaces to be removed is EMPTY if a chip mode change is required - in
     * that case ALL the interfaces on the current chip have to be removed first.
     *
     * Response determined based on:
     * - Mode configuration: i.e. could the mode support the interface type in principle
     * - Priority information: i.e. are we 'allowed' to remove interfaces in order to create the
     *   requested interface
     */
    private IfaceCreationData canIfaceComboSupportRequest(WifiChipInfo chipInfo,
            IWifiChip.ChipMode chipMode, int[] chipIfaceCombo, int ifaceType, boolean lowPriority) {
        if (VDBG) {
            Log.d(TAG, "canIfaceComboSupportRequest: chipInfo=" + chipInfo + ", chipMode="
                    + chipMode + ", chipIfaceCombo=" + chipIfaceCombo + ", ifaceType=" + ifaceType
                    + ", lowPriority=" + lowPriority);
        }

        // short-circuit: does the chipIfaceCombo even support the requested type?
        if (chipIfaceCombo[ifaceType] == 0) {
            if (VDBG) Log.d(TAG, "Requested type not supported by combo");
            return null;
        }

        boolean isChipModeChangeProposed =
                chipInfo.currentModeIdValid && chipInfo.currentModeId != chipMode.id;

        // short-circuit: can't change chip-mode if an existing interface on this chip has a higher
        // priority than the requested interface
        if (isChipModeChangeProposed) {
            for (int type: IFACE_TYPES_BY_PRIORITY) {
                if (chipInfo.ifaces[type].length != 0) {
                    if (lowPriority) {
                        if (VDBG) {
                            Log.d(TAG, "Couldn't delete existing type " + type
                                    + " interfaces for a low priority request");
                        }
                        return null;
                    }
                    if (!allowedToDeleteIfaceTypeForRequestedType(type, ifaceType,
                            chipInfo.ifaces, chipInfo.ifaces[type].length)) {
                        if (VDBG) {
                            Log.d(TAG, "Couldn't delete existing type " + type
                                    + " interfaces for requested type");
                        }
                        return null;
                    }
                }
            }

            // but if priority allows the mode change then we're good to go
            IfaceCreationData ifaceCreationData = new IfaceCreationData();
            ifaceCreationData.chipInfo = chipInfo;
            ifaceCreationData.chipModeId = chipMode.id;

            return ifaceCreationData;
        }

        // possibly supported
        List interfacesToBeRemovedFirst = new ArrayList<>();

        for (int type: IFACE_TYPES_BY_PRIORITY) {
            int tooManyInterfaces = chipInfo.ifaces[type].length - chipIfaceCombo[type];

            // need to count the requested interface as well
            if (type == ifaceType) {
                tooManyInterfaces += 1;
            }

            if (tooManyInterfaces > 0) { // may need to delete some
                if (lowPriority) {
                    if (VDBG) {
                        Log.d(TAG, "Couldn't delete existing type " + type
                                + " interfaces for a low priority request");
                    }
                    return null;
                }

                if (!allowedToDeleteIfaceTypeForRequestedType(type, ifaceType, chipInfo.ifaces,
                        tooManyInterfaces)) {
                    if (VDBG) {
                        Log.d(TAG, "Would need to delete some higher priority interfaces");
                    }
                    return null;
                }

                // delete the most recently created interfaces or LOW priority interfaces
                interfacesToBeRemovedFirst = selectInterfacesToDelete(tooManyInterfaces,
                        chipInfo.ifaces[type]);
            }
        }

        IfaceCreationData ifaceCreationData = new IfaceCreationData();
        ifaceCreationData.chipInfo = chipInfo;
        ifaceCreationData.chipModeId = chipMode.id;
        ifaceCreationData.interfacesToBeRemovedFirst = interfacesToBeRemovedFirst;

        return ifaceCreationData;
    }

    /**
     * Checks whether the input chip-iface-combo can support the requested interface type: if not
     * then returns null, if yes then returns information containing the list of interfaces which
     * would have to be removed first before the requested interface can be created.
     *
     * Note: the list of interfaces to be removed is EMPTY if a chip mode change is required - in
     * that case ALL the interfaces on the current chip have to be removed first.
     *
     * Response determined based on:
     * - Mode configuration: i.e. could the mode support the interface type in principle
     * - Priority information: i.e. are we 'allowed' to remove interfaces in order to create the
     *   requested interface
     */

讲的很明白了,看下当前combo是否支持请求创建的interface type,如果不可以支持返回null,否则返回要移除挪位置的接口。移除由两个因素决定,mode configuration和priority,更详细的rule如下

    /**
     * Returns true if we're allowed to delete the existing interface type for the requested
     * interface type.
     *
     * Rules - applies in order:
     *
     * General rules:
     * 1. No interface will be destroyed for a requested interface of the same type
     * 2. No interface will be destroyed if one of the requested interfaces already exists
     * 3. If there are >1 interface of an existing type, then it is ok to destroy that type
     *    interface
     *
     * Type-specific rules (but note that the general rules are appied first):
     * 4. Request for AP or STA will destroy any other interface
     * 5. Request for P2P will destroy NAN-only (but will destroy a second STA per #3)
     * 6. Request for NAN will not destroy any interface (but will destroy a second STA per #3)
     *
     * Note: the 'numNecessaryInterfaces' is used to specify how many interfaces would be needed to
     * be deleted. This is used to determine whether there are that many low priority interfaces
     * of the requested type to delete.
     */
    private boolean allowedToDeleteIfaceTypeForRequestedType(int existingIfaceType,
            int requestedIfaceType, WifiIfaceInfo[][] currentIfaces, int numNecessaryInterfaces) {
        // rule 0: check for any low priority interfaces
        int numAvailableLowPriorityInterfaces = 0;
        for (InterfaceCacheEntry entry : mInterfaceInfoCache.values()) {
            if (entry.type == existingIfaceType && entry.isLowPriority) {
                numAvailableLowPriorityInterfaces++;
            }
        }
        if (numAvailableLowPriorityInterfaces >= numNecessaryInterfaces) {
            return true;
        }

        // rule 1
        if (existingIfaceType == requestedIfaceType) {
            return false;
        }

        // rule 2
        if (currentIfaces[requestedIfaceType].length != 0) {
            return false;
        }

        // rule 3
        if (currentIfaces[existingIfaceType].length > 1) {
            return true;
        }

        // rule 6
        if (requestedIfaceType == IfaceType.NAN) {
            return false;
        }

        // rule 5
        if (requestedIfaceType == IfaceType.P2P) {
            return existingIfaceType == IfaceType.NAN;
        }

        // rule 4, the requestIfaceType is either AP or STA
        return true;
    }

 

2.2.3 compareIfaceCreationData

    /**
     * Compares two options to create an interface and determines which is the 'best'. Returns
     * true if proposal 1 (val1) is better, other false.
     *
     * Note: both proposals are 'acceptable' bases on priority criteria.
     *
     * Criteria:
     * - Proposal is better if it means removing fewer high priority interfaces
     */
    private boolean compareIfaceCreationData(IfaceCreationData val1, IfaceCreationData val2) {
        if (VDBG) Log.d(TAG, "compareIfaceCreationData: val1=" + val1 + ", val2=" + val2);

        // deal with trivial case of one or the other being null
        if (val1 == null) {
            return false;
        } else if (val2 == null) {
            return true;
        }

        for (int type: IFACE_TYPES_BY_PRIORITY) {
            // # of interfaces to be deleted: the list or all interfaces of the type if mode change
            int numIfacesToDelete1 = 0;
            if (val1.chipInfo.currentModeIdValid
                    && val1.chipInfo.currentModeId != val1.chipModeId) {
                numIfacesToDelete1 = val1.chipInfo.ifaces[type].length;
            } else {
                numIfacesToDelete1 = val1.interfacesToBeRemovedFirst.size();
            }

            int numIfacesToDelete2 = 0;
            if (val2.chipInfo.currentModeIdValid
                    && val2.chipInfo.currentModeId != val2.chipModeId) {
                numIfacesToDelete2 = val2.chipInfo.ifaces[type].length;
            } else {
                numIfacesToDelete2 = val2.interfacesToBeRemovedFirst.size();
            }

            if (numIfacesToDelete1 < numIfacesToDelete2) {
                if (VDBG) {
                    Log.d(TAG, "decision based on type=" + type + ": " + numIfacesToDelete1
                            + " < " + numIfacesToDelete2);
                }
                return true;
            }
        }

        // arbitrary - flip a coin
        if (VDBG) Log.d(TAG, "proposals identical - flip a coin");
        return false;
    }

比较待选选项,移除较少的接口的方案优先。

 

2.3 executeChipReconfiguration

    /**
     * Performs chip reconfiguration per the input:
     * - Removes the specified interfaces
     * - Reconfigures the chip to the new chip mode (if necessary)
     * - Creates the new interface
     *
     * Returns the newly created interface or a null on any error.
     */
    private IWifiIface executeChipReconfiguration(IfaceCreationData ifaceCreationData,
            int ifaceType) {
        if (mDbg) {
            Log.d(TAG, "executeChipReconfiguration: ifaceCreationData=" + ifaceCreationData
                    + ", ifaceType=" + ifaceType);
        }
        synchronized (mLock) {
            try {
                // is this a mode change?
                boolean isModeConfigNeeded = !ifaceCreationData.chipInfo.currentModeIdValid
                        || ifaceCreationData.chipInfo.currentModeId != ifaceCreationData.chipModeId;
                if (mDbg) Log.d(TAG, "isModeConfigNeeded=" + isModeConfigNeeded);

                // first delete interfaces/change modes
                if (isModeConfigNeeded) {
                    // remove all interfaces pre mode-change
                    // TODO: is this necessary? note that even if we don't want to explicitly
                    // remove the interfaces we do need to call the onDeleted callbacks - which
                    // this does
                    for (WifiIfaceInfo[] ifaceInfos: ifaceCreationData.chipInfo.ifaces) {
                        for (WifiIfaceInfo ifaceInfo: ifaceInfos) {
                            removeIfaceInternal(ifaceInfo.iface); // ignore return value
                        }
                    }

                    WifiStatus status = ifaceCreationData.chipInfo.chip.configureChip(
                            ifaceCreationData.chipModeId);
                    if (status.code != WifiStatusCode.SUCCESS) {
                        Log.e(TAG, "executeChipReconfiguration: configureChip error: "
                                + statusString(status));
                        return null;
                    }
                } else {
                    // remove all interfaces on the delete list
                    for (WifiIfaceInfo ifaceInfo: ifaceCreationData.interfacesToBeRemovedFirst) {
                        removeIfaceInternal(ifaceInfo.iface); // ignore return value
                    }
                }

                // create new interface
                Mutable statusResp = new Mutable<>();
                Mutable ifaceResp = new Mutable<>();
                switch (ifaceType) {
                    case IfaceType.STA:
                        ifaceCreationData.chipInfo.chip.createStaIface(
                                (WifiStatus status, IWifiStaIface iface) -> {
                                    statusResp.value = status;
                                    ifaceResp.value = iface;
                                });
                        break;

hardware/interfaces/wifi/1.2/default/wifi_chip.cpp

Return WifiChip::configureChip(ChipModeId mode_id,
                                     configureChip_cb hidl_status_cb) {
    return validateAndCallWithLock(
        this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
        &WifiChip::configureChipInternal, hidl_status_cb, mode_id);
}

WifiStatus WifiChip::configureChipInternal(
    /* NONNULL */ std::unique_lock* lock,
    ChipModeId mode_id) {
    if (!isValidModeId(mode_id)) {
        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
    }
    if (mode_id == current_mode_id_) {
        LOG(DEBUG) << "Already in the specified mode " << mode_id;
        return createWifiStatus(WifiStatusCode::SUCCESS);
    }
    WifiStatus status = handleChipConfiguration(lock, mode_id);
    if (status.code != WifiStatusCode::SUCCESS) {
        for (const auto& callback : event_cb_handler_.getCallbacks()) {
            if (!callback->onChipReconfigureFailure(status).isOk()) {
                LOG(ERROR)
                    << "Failed to invoke onChipReconfigureFailure callback";
            }
        }
        return status;
    }
    for (const auto& callback : event_cb_handler_.getCallbacks()) {
        if (!callback->onChipReconfigured(mode_id).isOk()) {
            LOG(ERROR) << "Failed to invoke onChipReconfigured callback";
        }
    }
    current_mode_id_ = mode_id;
    LOG(INFO) << "Configured chip in mode " << mode_id;
    return status;
}

WifiStatus WifiChip::handleChipConfiguration(
    /* NONNULL */ std::unique_lock* lock,
    ChipModeId mode_id) {
    // If the chip is already configured in a different mode, stop
    // the legacy HAL and then start it after firmware mode change.
    if (isValidModeId(current_mode_id_)) {
        LOG(INFO) << "Reconfiguring chip from mode " << current_mode_id_
                  << " to mode " << mode_id;
        invalidateAndRemoveAllIfaces();
        legacy_hal::wifi_error legacy_status =
            legacy_hal_.lock()->stop(lock, []() {});
        if (legacy_status != legacy_hal::WIFI_SUCCESS) {
            LOG(ERROR) << "Failed to stop legacy HAL: "
                       << legacyErrorToString(legacy_status);
            return createWifiStatusFromLegacyError(legacy_status);
        }
    }
    // Firmware mode change not needed for V2 devices.
    bool success = true;
    if (mode_id == kV1StaChipModeId) {
        success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA);
    } else if (mode_id == kV1ApChipModeId) {
        success = mode_controller_.lock()->changeFirmwareMode(IfaceType::AP);
    }
    if (!success) {
        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
    }
    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->start();
    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
        LOG(ERROR) << "Failed to start legacy HAL: "
                   << legacyErrorToString(legacy_status);
        return createWifiStatusFromLegacyError(legacy_status);
    }
    // Every time the HAL is restarted, we need to register the
    // radio mode change callback.
    WifiStatus status = registerRadioModeChangeCallback();
    if (status.code != WifiStatusCode::SUCCESS) {
        // This probably is not a critical failure?
        LOG(ERROR) << "Failed to register radio mode change callback";
    }
    return createWifiStatus(WifiStatusCode::SUCCESS);
}

根据chipmode修改chip config,其中

// Firmware mode change not needed for V2 devices.

  • kV1StaChipModeId Firmware 切换为sta模式
  • kV1ApChipModeId Firmware 切换为ap模式

 

Return WifiChip::createStaIface(createStaIface_cb hidl_status_cb) {
    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
                           &WifiChip::createStaIfaceInternal, hidl_status_cb);
}

std::pair> WifiChip::createStaIfaceInternal() {
    if (!canCurrentModeSupportIfaceOfType(IfaceType::STA)) {
        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
    }
    std::string ifname = allocateApOrStaIfaceName();
    sp iface = new WifiStaIface(ifname, legacy_hal_);
    sta_ifaces_.push_back(iface);
    for (const auto& callback : event_cb_handler_.getCallbacks()) {
        if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) {
            LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
        }
    }
    return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
}

// Return "wlan0", if "wlan0" is not already in use, else return "wlan1".
// This is based on the assumption that we'll have a max of 2 concurrent
// AP/STA ifaces.
std::string WifiChip::allocateApOrStaIfaceName() {
    auto ap_iface = findUsingName(ap_ifaces_, getWlan0IfaceName());
    auto sta_iface = findUsingName(sta_ifaces_, getWlan0IfaceName());
    if (!ap_iface.get() && !sta_iface.get()) {
        return getWlan0IfaceName();
    }
    ap_iface = findUsingName(ap_ifaces_, getWlan1IfaceName());
    sta_iface = findUsingName(sta_ifaces_, getWlan1IfaceName());
    if (!ap_iface.get() && !sta_iface.get()) {
        return getWlan1IfaceName();
    }
    // This should never happen. We screwed up somewhere if it did.
    CHECK(0) << "wlan0 and wlan1 in use already!";
    return {};
}

这边简单来看只是初始化了一个WifiStaIface,并没有实际iface的创建,然后有个回调,会调用callback的onIfaceAdded。

iface的创建真正和driver/kernel关联起来是在哪里呢?

            if (mWificondControl.setupInterfaceForClientMode(iface.name) == null) {
                Log.e(TAG, "Failed to setup iface in wificond on " + iface);
                teardownInterface(iface.name);
                mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond();
                return null;
            }
            if (!mSupplicantStaIfaceHal.setupIface(iface.name)) {
                Log.e(TAG, "Failed to setup iface in supplicant on " + iface);
                teardownInterface(iface.name);
                mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
                return null;
            }

看起来是下面两步,一个是在wificond,一个是在supplicant中setup iface,待续

 

3.总结

本文主要就根据chip info创建sta iface的流程进行了梳理,说明了一个浅显的道理,上层功能受底层限制或软件受限于硬件。

 

 

你可能感兴趣的:(Wifi)