前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android中WiFi的RX与TX获取流程以及配置

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

作者头像
用户7557625
发布2020-07-15 11:02:06
2.1K0
发布2020-07-15 11:02:06
举报

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);
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-03-28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档