Understanding WiFi Performance

Search This thread

jeffsf

Senior Member
Mar 7, 2011
1,121
976
San Francisco
There has been a lot of reports of WiFi not performing as well with the current crop of ICS ROMs as compared to GB ROMs. There certainly is a difference in the reported signal strength between them; that is not debated. The question is if there is a performance difference between ICS ROMs and GB ROMs.

This thread discusses how WiFi works under Android, some opinions about what is "different" between GB and current ICS ROMs, and provides tools that allow one to perform tests about the actual performance of the WiFi of a specific configuration, as well as the reported RSSI.

Brief summary:

The important measure of WiFi performance is throughput.

The RSSI is the "Reported Signal Strength Indication" -- not a measurement of actual field strength. The RSSI is provided mainly as an indication of signal strength and is subject to "calibration" at several points; it does not measure performance. The link speed reported also does not measure performance; in fact, it has been shown that higher link speeds can result in lower throughput as the modulation and error correction schemes are different.

The throughput of WiFI connections have been tested comparing "stock" (with AntonX kernel) GB to an early stable build of AOKP. Testing was done under controlled conditions using strong and weak signals, from three APs; a WRT-54g with "rubber duckie" antennas in a cross-pol configuration, a WRT-54g with a cross-pol flat-panel gain antenna, and one WNDR3700 with its internal antenna. All APs were running OpenWRT and interconnected using GigE trunking through Netgear GS108T and Netgear GS724Tv2 switches. The power output of these were all controlled and adjusted from their maximum transmit power to the level at which the throughput dropped below 1 Mbps. At least five measurements were made for every configuration and power level.

No significant difference in throughput was seen between GB and ICS. In some cases, the ICS test performed slightly better than the GB test. Differences were less than 10%.

The RSSI from the supplicant appeared to be in dB; a 10 dB reduction in transmit power reduced the RSSI by approximately 10 on both GB and ICS configurations. However the reference point for them were very different; GB reporting positive numbers over 200 and ICS reporting negative numbers roughly in the -50 to -100 range.

As the throughput performance is comparable on both ROMs, it is believed that the "issues" being seen are related to the "calibration" of the RSSI. Lower levels than Android code expects have two primary impacts:
  • The UI represents the same actual signal strength with fewer bars
  • Android will not display or connect to certain APs as their RSSI is lower than its fixed threshold
 
Last edited:

jeffsf

Senior Member
Mar 7, 2011
1,121
976
San Francisco
In depth:

A basic understanding of how WiFi works in general, as well as in Linux is valuable.

The Broadcom BCM4329 data sheet has a block diagram that may be useful in understanding the chip's functions. I'll go through the recieve end of things, since that is where the "signal strength" information comes from. The transmit side is similar.

There is an antenna in the phone that converts radio-frequency (RF) electrical signals to radio waves and vice versa. This has a "gain" that relates the strength of the electrical signal and the strength of the radio wave.

Inside the chip, the RF signal is converted to a "baseband" signal using an analog-to-digital converted (ADC) and sent to an internal processor. The processor uses microcode to know how to demodulate the signal (extract the "bits" from the shape of the RF waves). Based on the numbers from the ADC, a number roughly representing "signal strength" is computed. For example, "32768" from the demodulated signal may mean "100" for signal strength. This reference point is picked by the chip manufacturer and might mean something in terms of physical signal strength (dbM, for example), when using the chip manufacturer's reference board. If you change the antenna, for example, it is no longer "calibrated" to anything. This demodulation process uses microcode that is downloaded into the chip on initialization by the driver. The chip also handles the low-level WiFi protocol; how to change channels, how to "associate" with a given access point (AP), how to scan available APs, how to do encryption, etc. This microcode is proprietary and generally supplied by the chip manufacturer.

There is a driver in the Linux kernel that is responsible for how to communicate with the chip and access its low-level functions in a "device independent" way. Think of it as someone that brings another person into the room with you, tells you who they are, then translates their Urdu to English and vice versa so you can have a conversation. This is open source in the kernel.

In most devices, from dedicated WiFi devices, through our phones and just about any computer running Linux, the next "person" in the chain is the "supplicant" -- It handles high-level commands and responses, including:
* Providing a list of available APs
* Connecting to a specific AP
* Managing lists of passwords for APs
* Providing the "Reported Signal Strength Indication" or RSSI
This is open source code in the Linux distribution

One thing to remember here is that RSSI is just that, reported and an indication of the signal strength. There is no guarantee what the numbers mean! By the time you get here, you've got an unknown antenna gain, a ADC-counts-to-strength conversion in the chip, and potentially another conversion in the driver.

Many phones and other devices have that factor in a "calibration file" that makes the output of the RSSI "look good" on the device's UI, or to other code in the device. This generally comes from the device manufacturer and it proprietary. In some cases, this has been reverse-engineered or supplied by the vendor. Other devices may have a /proc/calibration device, which can be used to send calibration information to the driver. This includes the bcm4329 driver in use by the "ICS" kernels:
Code:
config BCM4329_NVRAM_PATH
        depends on BCM4329
        string "NVRAM path"
        default "/proc/calibration"
        ---help---
          Path to the calibration file.
Code:
CONFIG_WLAN=y
CONFIG_BCM4329_PURE_ANDROID=y
CONFIG_BCM4329=m
CONFIG_BCM4329_FW_PATH="/system/vendor/firmware/fw_bcm4329.bin"
CONFIG_BCM4329_NVRAM_PATH="/system/vendor/firmware/nvram_net.txt"
That file contains some "magic incantations" including
Code:
# 11g rssi params
rssismf2g=0xa,0xa,0xa
rssismc2g=0xb,0xb,0xa
rssisav2g=0x3,0x3,0x3
From there, we go to the Android level. Java code communicates with the supplicant and gets lists of APs, their RSSI, and supplies passwords, when needed. With the information it has on RSSI, it converts it to "bars" using something equally arbitrary. You can look at the source in frameworks/base/wifi/java/android/net/wifi/

In WifiManager.java you can see how Android views WiFi and how it handles things. You can even see how to "fix" the issue at the Android level from this (the commented-out MIN_RSSI and MAX_RSSI are "stock" -- the numbers there are ones that are based on the throughput measurements I made).
Code:
    /** Anything worse than or equal to this will show 0 bars. */
    // private static final int MIN_RSSI = -100;
    private static final int MIN_RSSI = -95;

    /** Anything better than or equal to this will show the max bars. */
    // private static final int MAX_RSSI = -55;
    private static final int MAX_RSSI = -65;
Code:
    /**
     * Calculates the level of the signal. This should be used any time a signal
     * is being shown.
     *
     * @param rssi The power of the signal measured in RSSI.
     * @param numLevels The number of levels to consider in the calculated
     *            level.
     * @return A level of the signal, given in the range of 0 to numLevels-1
     *         (both inclusive).
     */
    public static int calculateSignalLevel(int rssi, int numLevels) {
        if (rssi <= MIN_RSSI) {
            return 0;
        } else if (rssi >= MAX_RSSI) {
            return numLevels - 1;
        } else {
            float inputRange = (MAX_RSSI - MIN_RSSI);
            float outputRange = (numLevels - 1);
            return (int)((float)(rssi - MIN_RSSI) * outputRange / inputRange);
        }
    }

If you're not Java-saavy, what is basically happening there is that Android says there are numLevel "bars" and they lie evenly between the MIN_RSSI and MAX_RSSI values. Other code reveals that anything below MIN_RSSI isn't shown to the user and isn't a candidate for a connection.

So, where does this leave us?

Changing your ROM shouldn't change the antenna on the device. So that's out.

The microcode is supplied by Broadcom and they'd have sales problems if it was bad, so I'll rule that one out too.

There is the possibility that the calibration in the driver has changed. Given the way that the display of the RSSI was bouncing around when those GB leaks were coming out, this seems like a strong possibility. (If anyone has those leaks still available, please let me know. I'd like to look at them and most were hosted on now-FBI-ified websites).

There are proprietary drivers from Broadcom, as well as three open-source versions in the Linux distribution. These include microcode. "We" are using one of the open-source ones. If it were "bad" then the SGS4G wouldn't be the only thing out there with an issue. I doubt this is the problem. The same goes for the supplicant; it is too widely used to have a significant issue.

So, this basically leaves "calibration" of the numbers reported by the chip to numbers that work well with Android.
 
Last edited:

jeffsf

Senior Member
Mar 7, 2011
1,121
976
San Francisco
How to test it yourself:

First, realize that anything, metal, plastic, wood, a glass of water, your mouse, your body, even your hand, within about two feet of your phone or the AP can dramatically change how it receives and sends the 2.4 GHz radio waves. Differences in position of about a centimeter are significant compared to the ~12.5 cm wavelength. For my test, I had a corner of my desk with a ridge so I could very accurately place the phone into the exact same place. I also taped down my USB cable (for adb), so it would be in the same place each time.

I ran two kinds of tests. The first is using netperf, which measures the throughput of the connection. This is really what matters -- not what some number of bars say, but how fast can I reliably send data over the link. I used TCP so that the impact of packet loss was included. You'll need a machine that can run netperf, as well as a binary for your phone. I've attached a binary built from source using the AOSP build tools. You can also use the Android NDK.

The second is to look at the average RSSI reported by the supplicant. The attached Perl script assumes that have adb running, then polls the supplicant every second for the BSSID (AP name) you specify in the code. It provides the read RSSI, as well as exponential averages over 10, 100, and 1000 samples.
 

Attachments

  • netperf-netserver.tar
    120 KB · Views: 36
  • wifi-signal-monitor.tar
    10 KB · Views: 48
Last edited:

lonoguge

Senior Member
Apr 27, 2012
402
56
I'm having trouble using Wifi tether. When ever I try to connect I get an error that says "WTF!! Your phone is automatically shutting off the connection" lol it was pretty funny first time I saw it. The wifi tether signal still shows up on the devices I connect to but they don't register it. Is there any work around or fix? I used the roms codename and beam for this btw.

Sent from my SGH-T959V using xda app-developers app
 

pisherthefisher

Senior Member
Jan 1, 2012
782
338
Very informative post like usual, thanks jeff.

Although the wifi signal is the same as gingerbread, it seems to disconnect in places where gingerbread wouldn't. For example, in my room I have no wifi signal bars in ics (it still shows the wifi icon though) and it tends to disconnect every now and then (this only happens when the signal isn't good. On gingerbread it always stays at 1 or 2 bars and never disconnects.

Is it possible to keep the wifi from disconnecting?

Sent from my SGH-T959V using xda app-developers app
 

jeffsf

Senior Member
Mar 7, 2011
1,121
976
San Francisco
[The WiFi] seems to disconnect in places where gingerbread wouldn't. For example, in my room I have no wifi signal bars in ics (it still shows the wifi icon though) and it tends to disconnect every now and then (this only happens when the signal isn't good. On gingerbread it always stays at 1 or 2 bars and never disconnects.

Is it possible to keep the wifi from disconnecting?

You should be able to "hack in 10 more" -- I haven't taken the time yet to determine if the kernel/driver is the best place to do it, or if it is in calculateSignalLevel() as shown above, or somewhere else.

For me, I find that if the signal level is that low, I have better throughput with T-Mobile, at least here in the San Francisco Bay Area. I realize others have different needs than I do and I'll be looking at it again with the "Aries" kernel for the SGS4G.
 
  • Like
Reactions: pisherthefisher

llinkll

Member
May 1, 2014
37
24
There has been a lot of reports of WiFi not performing as well with the current crop of ICS ROMs as compared to GB ROMs. There certainly is a difference in the reported signal strength between them; that is not debated. The question is if there is a performance difference between ICS ROMs and GB ROMs.



Thanks for this thread.
 

Top Liked Posts

  • There are no posts matching your filters.
  • 19
    There has been a lot of reports of WiFi not performing as well with the current crop of ICS ROMs as compared to GB ROMs. There certainly is a difference in the reported signal strength between them; that is not debated. The question is if there is a performance difference between ICS ROMs and GB ROMs.

    This thread discusses how WiFi works under Android, some opinions about what is "different" between GB and current ICS ROMs, and provides tools that allow one to perform tests about the actual performance of the WiFi of a specific configuration, as well as the reported RSSI.

    Brief summary:

    The important measure of WiFi performance is throughput.

    The RSSI is the "Reported Signal Strength Indication" -- not a measurement of actual field strength. The RSSI is provided mainly as an indication of signal strength and is subject to "calibration" at several points; it does not measure performance. The link speed reported also does not measure performance; in fact, it has been shown that higher link speeds can result in lower throughput as the modulation and error correction schemes are different.

    The throughput of WiFI connections have been tested comparing "stock" (with AntonX kernel) GB to an early stable build of AOKP. Testing was done under controlled conditions using strong and weak signals, from three APs; a WRT-54g with "rubber duckie" antennas in a cross-pol configuration, a WRT-54g with a cross-pol flat-panel gain antenna, and one WNDR3700 with its internal antenna. All APs were running OpenWRT and interconnected using GigE trunking through Netgear GS108T and Netgear GS724Tv2 switches. The power output of these were all controlled and adjusted from their maximum transmit power to the level at which the throughput dropped below 1 Mbps. At least five measurements were made for every configuration and power level.

    No significant difference in throughput was seen between GB and ICS. In some cases, the ICS test performed slightly better than the GB test. Differences were less than 10%.

    The RSSI from the supplicant appeared to be in dB; a 10 dB reduction in transmit power reduced the RSSI by approximately 10 on both GB and ICS configurations. However the reference point for them were very different; GB reporting positive numbers over 200 and ICS reporting negative numbers roughly in the -50 to -100 range.

    As the throughput performance is comparable on both ROMs, it is believed that the "issues" being seen are related to the "calibration" of the RSSI. Lower levels than Android code expects have two primary impacts:
    • The UI represents the same actual signal strength with fewer bars
    • Android will not display or connect to certain APs as their RSSI is lower than its fixed threshold
    16
    How to test it yourself:

    First, realize that anything, metal, plastic, wood, a glass of water, your mouse, your body, even your hand, within about two feet of your phone or the AP can dramatically change how it receives and sends the 2.4 GHz radio waves. Differences in position of about a centimeter are significant compared to the ~12.5 cm wavelength. For my test, I had a corner of my desk with a ridge so I could very accurately place the phone into the exact same place. I also taped down my USB cable (for adb), so it would be in the same place each time.

    I ran two kinds of tests. The first is using netperf, which measures the throughput of the connection. This is really what matters -- not what some number of bars say, but how fast can I reliably send data over the link. I used TCP so that the impact of packet loss was included. You'll need a machine that can run netperf, as well as a binary for your phone. I've attached a binary built from source using the AOSP build tools. You can also use the Android NDK.

    The second is to look at the average RSSI reported by the supplicant. The attached Perl script assumes that have adb running, then polls the supplicant every second for the BSSID (AP name) you specify in the code. It provides the read RSSI, as well as exponential averages over 10, 100, and 1000 samples.
    10
    In depth:

    A basic understanding of how WiFi works in general, as well as in Linux is valuable.

    The Broadcom BCM4329 data sheet has a block diagram that may be useful in understanding the chip's functions. I'll go through the recieve end of things, since that is where the "signal strength" information comes from. The transmit side is similar.

    There is an antenna in the phone that converts radio-frequency (RF) electrical signals to radio waves and vice versa. This has a "gain" that relates the strength of the electrical signal and the strength of the radio wave.

    Inside the chip, the RF signal is converted to a "baseband" signal using an analog-to-digital converted (ADC) and sent to an internal processor. The processor uses microcode to know how to demodulate the signal (extract the "bits" from the shape of the RF waves). Based on the numbers from the ADC, a number roughly representing "signal strength" is computed. For example, "32768" from the demodulated signal may mean "100" for signal strength. This reference point is picked by the chip manufacturer and might mean something in terms of physical signal strength (dbM, for example), when using the chip manufacturer's reference board. If you change the antenna, for example, it is no longer "calibrated" to anything. This demodulation process uses microcode that is downloaded into the chip on initialization by the driver. The chip also handles the low-level WiFi protocol; how to change channels, how to "associate" with a given access point (AP), how to scan available APs, how to do encryption, etc. This microcode is proprietary and generally supplied by the chip manufacturer.

    There is a driver in the Linux kernel that is responsible for how to communicate with the chip and access its low-level functions in a "device independent" way. Think of it as someone that brings another person into the room with you, tells you who they are, then translates their Urdu to English and vice versa so you can have a conversation. This is open source in the kernel.

    In most devices, from dedicated WiFi devices, through our phones and just about any computer running Linux, the next "person" in the chain is the "supplicant" -- It handles high-level commands and responses, including:
    * Providing a list of available APs
    * Connecting to a specific AP
    * Managing lists of passwords for APs
    * Providing the "Reported Signal Strength Indication" or RSSI
    This is open source code in the Linux distribution

    One thing to remember here is that RSSI is just that, reported and an indication of the signal strength. There is no guarantee what the numbers mean! By the time you get here, you've got an unknown antenna gain, a ADC-counts-to-strength conversion in the chip, and potentially another conversion in the driver.

    Many phones and other devices have that factor in a "calibration file" that makes the output of the RSSI "look good" on the device's UI, or to other code in the device. This generally comes from the device manufacturer and it proprietary. In some cases, this has been reverse-engineered or supplied by the vendor. Other devices may have a /proc/calibration device, which can be used to send calibration information to the driver. This includes the bcm4329 driver in use by the "ICS" kernels:
    Code:
    config BCM4329_NVRAM_PATH
            depends on BCM4329
            string "NVRAM path"
            default "/proc/calibration"
            ---help---
              Path to the calibration file.
    Code:
    CONFIG_WLAN=y
    CONFIG_BCM4329_PURE_ANDROID=y
    CONFIG_BCM4329=m
    CONFIG_BCM4329_FW_PATH="/system/vendor/firmware/fw_bcm4329.bin"
    CONFIG_BCM4329_NVRAM_PATH="/system/vendor/firmware/nvram_net.txt"
    That file contains some "magic incantations" including
    Code:
    # 11g rssi params
    rssismf2g=0xa,0xa,0xa
    rssismc2g=0xb,0xb,0xa
    rssisav2g=0x3,0x3,0x3
    From there, we go to the Android level. Java code communicates with the supplicant and gets lists of APs, their RSSI, and supplies passwords, when needed. With the information it has on RSSI, it converts it to "bars" using something equally arbitrary. You can look at the source in frameworks/base/wifi/java/android/net/wifi/

    In WifiManager.java you can see how Android views WiFi and how it handles things. You can even see how to "fix" the issue at the Android level from this (the commented-out MIN_RSSI and MAX_RSSI are "stock" -- the numbers there are ones that are based on the throughput measurements I made).
    Code:
        /** Anything worse than or equal to this will show 0 bars. */
        // private static final int MIN_RSSI = -100;
        private static final int MIN_RSSI = -95;
    
        /** Anything better than or equal to this will show the max bars. */
        // private static final int MAX_RSSI = -55;
        private static final int MAX_RSSI = -65;
    Code:
        /**
         * Calculates the level of the signal. This should be used any time a signal
         * is being shown.
         *
         * @param rssi The power of the signal measured in RSSI.
         * @param numLevels The number of levels to consider in the calculated
         *            level.
         * @return A level of the signal, given in the range of 0 to numLevels-1
         *         (both inclusive).
         */
        public static int calculateSignalLevel(int rssi, int numLevels) {
            if (rssi <= MIN_RSSI) {
                return 0;
            } else if (rssi >= MAX_RSSI) {
                return numLevels - 1;
            } else {
                float inputRange = (MAX_RSSI - MIN_RSSI);
                float outputRange = (numLevels - 1);
                return (int)((float)(rssi - MIN_RSSI) * outputRange / inputRange);
            }
        }

    If you're not Java-saavy, what is basically happening there is that Android says there are numLevel "bars" and they lie evenly between the MIN_RSSI and MAX_RSSI values. Other code reveals that anything below MIN_RSSI isn't shown to the user and isn't a candidate for a connection.

    So, where does this leave us?

    Changing your ROM shouldn't change the antenna on the device. So that's out.

    The microcode is supplied by Broadcom and they'd have sales problems if it was bad, so I'll rule that one out too.

    There is the possibility that the calibration in the driver has changed. Given the way that the display of the RSSI was bouncing around when those GB leaks were coming out, this seems like a strong possibility. (If anyone has those leaks still available, please let me know. I'd like to look at them and most were hosted on now-FBI-ified websites).

    There are proprietary drivers from Broadcom, as well as three open-source versions in the Linux distribution. These include microcode. "We" are using one of the open-source ones. If it were "bad" then the SGS4G wouldn't be the only thing out there with an issue. I doubt this is the problem. The same goes for the supplicant; it is too widely used to have a significant issue.

    So, this basically leaves "calibration" of the numbers reported by the chip to numbers that work well with Android.
    1
    [The WiFi] seems to disconnect in places where gingerbread wouldn't. For example, in my room I have no wifi signal bars in ics (it still shows the wifi icon though) and it tends to disconnect every now and then (this only happens when the signal isn't good. On gingerbread it always stays at 1 or 2 bars and never disconnects.

    Is it possible to keep the wifi from disconnecting?

    You should be able to "hack in 10 more" -- I haven't taken the time yet to determine if the kernel/driver is the best place to do it, or if it is in calculateSignalLevel() as shown above, or somewhere else.

    For me, I find that if the signal level is that low, I have better throughput with T-Mobile, at least here in the San Francisco Bay Area. I realize others have different needs than I do and I'll be looking at it again with the "Aries" kernel for the SGS4G.