Android中WiFi的RX与TX获取流程以及配置

2020-07-15 11:02:06 浏览数 (1)

Android中的RX与TX,即WiFI的传输速率与接收速率,是在WifiConfigController里添加的,可以看到,只有它们的值不为0时,才会显示。

下面是代码逻辑:

/packages/apps/Settings/src/com/android/settings/wifi/WifiConfigController.java

代码语言:javascript复制
private void initWifiConfigController(AccessPoint accessPoint, int mode) {
     WifiInfo info = mAccessPoint.getInfo();
      if (info != null && info.getTxLinkSpeedMbps() != WifiInfo.LINK_SPEED_UNKNOWN) {
          addRow(group, R.string.tx_wifi_speed, String.format(
                  res.getString(R.string.tx_link_speed), info.getTxLinkSpeedMbps()));
      }

      if (info != null && info.getRxLinkSpeedMbps() != WifiInfo.LINK_SPEED_UNKNOWN) {
          addRow(group, R.string.rx_wifi_speed, String.format(
                  res.getString(R.string.rx_link_speed), info.getRxLinkSpeedMbps()));
      }
}

/frameworks/base/wifi/java/android/net/wifi/WifiInfo.java

代码语言:javascript复制
/**
   * Returns the current transmit link speed in Mbps.
   * @return the Tx link speed or {@link #LINK_SPEED_UNKNOWN} if link speed is unknown.
   * @see #LINK_SPEED_UNKNOWN
   */
  @IntRange(from = -1)
  public int getTxLinkSpeedMbps() {
      return mTxLinkSpeed;
  }

  /**
   * Update the last transmitted packet bit rate in Mbps.
   * @hide
   */
  public void setTxLinkSpeedMbps(int txLinkSpeed) {
      mTxLinkSpeed = txLinkSpeed;
}

/frameworks/opt/net/wifi/service/java/com/android/server/wifi/ClientModeImpl.java

代码语言:javascript复制
   private void fetchRssiLinkSpeedAndFrequencyNative() {
        WifiNative.SignalPollResult pollResult = mWifiNative.signalPoll(mInterfaceName);
        if (pollResult == null) {
            return;
        }

        int newRssi = pollResult.currentRssi;
        int newTxLinkSpeed = pollResult.txBitrate;
        int newFrequency = pollResult.associationFrequency;
        int newRxLinkSpeed = pollResult.rxBitrate;

        if (mVerboseLoggingEnabled) {
            logd("fetchRssiLinkSpeedAndFrequencyNative rssi="   newRssi
                      " TxLinkspeed="   newTxLinkSpeed   " freq="   newFrequency
                      " RxLinkSpeed="   newRxLinkSpeed);
        }

        /*
         * set Tx link speed only if it is valid
         */
        if (newTxLinkSpeed > 0) {
            mWifiInfo.setLinkSpeed(newTxLinkSpeed);
            mWifiInfo.setTxLinkSpeedMbps(newTxLinkSpeed);
        }
        /*
         * set Rx link speed only if it is valid
         */
        if (newRxLinkSpeed > 0) {
            mWifiInfo.setRxLinkSpeedMbps(newRxLinkSpeed);
        }
        if (newFrequency > 0) {
            mWifiInfo.setFrequency(newFrequency);
        }
        mWifiConfigManager.updateScanDetailCacheFromWifiInfo(mWifiInfo);
        /*
         * Increment various performance metrics
         */
        mWifiMetrics.handlePollResult(mWifiInfo);
    }

/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java

代码语言:javascript复制
  public SignalPollResult signalPoll(@NonNull String ifaceName) {
        return mWificondControl.signalPoll(ifaceName);
    }

/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WificondControl.java

代码语言:javascript复制
  public WifiNative.SignalPollResult signalPoll(@NonNull String ifaceName) {
        IClientInterface iface = getClientInterface(ifaceName);
        if (iface == null) {
            Log.e(TAG, "No valid wificond client interface handler");
            return null;
        }

        int[] resultArray;
        try {
            resultArray = iface.signalPoll();
            if (resultArray == null || resultArray.length != 4) {
                Log.e(TAG, "Invalid signal poll result from wificond");
                return null;
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to do signal polling due to remote exception");
            return null;
        }
        WifiNative.SignalPollResult pollResult = new WifiNative.SignalPollResult();
        pollResult.currentRssi = resultArray[0];
        pollResult.txBitrate = resultArray[1];
        pollResult.associationFrequency = resultArray[2];
        pollResult.rxBitrate = resultArray[3];
        return pollResult;
    }

/system/connectivity/wificond/client_interface_binder.cpp

代码语言:javascript复制
Status ClientInterfaceBinder::signalPoll(
    vector<int32_t>* out_signal_poll_results) {
  if (impl_ == nullptr) {
    return Status::ok();
  }
  impl_->SignalPoll(out_signal_poll_results);
  return Status::ok();
}

/system/connectivity/wificond/client_interface_impl.cpp

代码语言:javascript复制
bool ClientInterfaceImpl::SignalPoll(vector<int32_t>* out_signal_poll_results) {
  if (!IsAssociated()) {
    LOG(INFO) << "Fail RSSI polling because wifi is not associated.";
    return false;
  }

  StationInfo station_info;
  if (!netlink_utils_->GetStationInfo(interface_index_,
                                      bssid_,
                                      &station_info)) {
    return false;
  }
  out_signal_poll_results->push_back(
      static_cast<int32_t>(station_info.current_rssi));
  // Convert from 100kbit/s to Mbps.
  out_signal_poll_results->push_back(
      static_cast<int32_t>(station_info.station_tx_bitrate/10));
  // Association frequency.
  out_signal_poll_results->push_back(
      static_cast<int32_t>(associate_freq_));
  // Convert from 100kbit/s to Mbps.
  out_signal_poll_results->push_back(
      static_cast<int32_t>(station_info.station_rx_bitrate/10));

  return true;
}

/system/connectivity/wificond/net/netlink_utils.cpp

代码语言:javascript复制
bool NetlinkUtils::GetStationInfo(uint32_t interface_index,
                                  const array<uint8_t, ETH_ALEN>& mac_address,
                                  StationInfo* out_station_info) {
  NL80211NestedAttr tx_bitrate_attr(0);
  uint32_t tx_bitrate = 0;
  if (sta_info.GetAttribute(NL80211_STA_INFO_TX_BITRATE,
                            &tx_bitrate_attr)) {
    if (!tx_bitrate_attr.GetAttributeValue(NL80211_RATE_INFO_BITRATE32,
                                         &tx_bitrate)) {
      // Return invalid tx rate to avoid breaking the get station cmd
      tx_bitrate = 0;
    }
  } else {
      LOG(ERROR) << "Failed to get NL80211_STA_INFO_TX_BITRATE";
      return false;
  }
  NL80211NestedAttr rx_bitrate_attr(0);
  uint32_t rx_bitrate = 0;
  if (sta_info.GetAttribute(NL80211_STA_INFO_RX_BITRATE,
                            &rx_bitrate_attr)) {
    if (!rx_bitrate_attr.GetAttributeValue(NL80211_RATE_INFO_BITRATE32,
                                         &rx_bitrate)) {
      // Return invalid rx rate to avoid breaking the get station cmd
      rx_bitrate = 0;
    }
  }
  *out_station_info = StationInfo(tx_good, tx_bad, tx_bitrate, current_rssi, rx_bitrate);
  return true;
}

/kernel/msm-4.9/net/wireless/nl80211.c

代码语言:javascript复制
static const struct genl_ops nl80211_ops[] = {
	{
		.cmd = NL80211_CMD_GET_STATION,
		.doit = nl80211_get_station,
		.dumpit = nl80211_dump_station,
		.policy = nl80211_policy,
		.internal_flags = NL80211_FLAG_NEED_NETDEV |
				  NL80211_FLAG_NEED_RTNL,
	},
	{
		.cmd = NL80211_CMD_SET_STATION,
		.doit = nl80211_set_station,
		.policy = nl80211_policy,
		.flags = GENL_UNS_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
	{
		.cmd = NL80211_CMD_NEW_STATION,
		.doit = nl80211_new_station,
		.policy = nl80211_policy,
		.flags = GENL_UNS_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
	{
		.cmd = NL80211_CMD_DEL_STATION,
		.doit = nl80211_del_station,
		.policy = nl80211_policy,
		.flags = GENL_UNS_ADMIN_PERM,
		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
				  NL80211_FLAG_NEED_RTNL,
	},
代码语言:javascript复制
static int nl80211_dump_station(struct sk_buff *skb,
				struct netlink_callback *cb)
{
	struct station_info sinfo;
	struct cfg80211_registered_device *rdev;
	struct wireless_dev *wdev;
	u8 mac_addr[ETH_ALEN];
	int sta_idx = cb->args[2];
	int err;

	rtnl_lock();
	err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
	if (err)
		goto out_err;

	if (!wdev->netdev) {
		err = -EINVAL;
		goto out_err;
	}

	if (!rdev->ops->dump_station) {
		err = -EOPNOTSUPP;
		goto out_err;
	}

	while (1) {
		memset(&sinfo, 0, sizeof(sinfo));
		err = rdev_dump_station(rdev, wdev->netdev, sta_idx,
					mac_addr, &sinfo);
		if (err == -ENOENT)
			break;
		if (err)
			goto out_err;

		if (nl80211_send_station(skb, NL80211_CMD_NEW_STATION,
				NETLINK_CB(cb->skb).portid,
				cb->nlh->nlmsg_seq, NLM_F_MULTI,
				rdev, wdev->netdev, mac_addr,
				&sinfo) < 0)
			goto out;

		sta_idx  ;
	}

 out:
	cb->args[2] = sta_idx;
	err = skb->len;
 out_err:
	rtnl_unlock();

	return err;
}

/kernel/msm-4.9/net/wireless/rdev-ops.h

代码语言:javascript复制
static inline int rdev_dump_station(struct cfg80211_registered_device *rdev,
				    struct net_device *dev, int idx, u8 *mac,
				    struct station_info *sinfo)
{
	int ret;
	trace_rdev_dump_station(&rdev->wiphy, dev, idx, mac);
	ret = rdev->ops->dump_station(&rdev->wiphy, dev, idx, mac, sinfo);
	trace_rdev_return_int_station_info(&rdev->wiphy, ret, sinfo);
	return ret;
}

如果NL80211_STA_INFO_TX_BITRATE没有被set,则上层得不到tx与rx数据。 /vendor/qcom/opensource/wlan/prima/CORE/HDD/src/wlan_hdd_cfg80211.c

代码语言:javascript复制
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && 
	!defined(WITH_BACKPORTS)
    sinfo->filled |= STATION_INFO_TX_BITRATE;
#else
    sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);

0 人点赞