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);