[Samsung Galaxy S (4G Model)] jeffsf:
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:

config BCM4329_NVRAM_PATH
depends on BCM4329
string "NVRAM path"
default "/proc/calibration"
---help---
Path to the calibration file.

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

# 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).

/** 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;

/**
* 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.