现在的位置: 首页 > 综合 > 正文

android wifi移植statusbar信号只显示一格的问题

2013年09月17日 ⁄ 综合 ⁄ 共 8814字 ⁄ 字号 评论关闭

android移植wifi后,在statusbar上信号老是只显示一格,这个问题碰到好多久了,由于最近做项目要修改这个,所以要解决,研究了一个多星期终于解决了,虽然还没有怎么弄懂,但是大致的说一下,希望对碰到这个问题的兄弟有帮助,写的不对的地方请大家多多指点,其实我也只有一点懂。

最开始我一直怀疑是framework的问题,所以研究了好久的framework。相关代码在如下目录(android2.3)

statusbar源码在framework/base/packages/SystemUI/src/com/android/systemui/statusbar中

设置中的wifi部分源码在packages/apps/Settings/src/com/android/settings/wifi中


我出现的问题是这样的,当wifi连接上后statusbar上面的wifi信号老是只显示一格,而setting里面的wifi信号有时候显示一格,有时候显示又是正常的,下面简单说下整个过程.

在statusbar源码目录中有一个StatusBarPolicy.java的文件,找到updateConnectivity函数,请看如下代码:

        case ConnectivityManager.TYPE_WIFI:
            mInetCondition = inetCondition;
            if (info.isConnected()) {
                mIsWifiConnected = true;
                int iconId;
                if (mLastWifiSignalLevel == -1) {
                    iconId = sWifiSignalImages[mInetCondition][0];
                } else {
                    iconId = sWifiSignalImages[mInetCondition][mLastWifiSignalLevel];
                }
                mService.setIcon("wifi", iconId, 0);
                // Show the icon since wi-fi is connected
                mService.setIconVisibility("wifi", true);
            } else {
                mLastWifiSignalLevel = -1;
                mIsWifiConnected = false;
                int iconId = sWifiSignalImages[0][0];

                mService.setIcon("wifi", iconId, 0);
                // Hide the icon since we're not connected
                mService.setIconVisibility("wifi", false);
            }
            updateSignalStrength(); // apply any change in mInetCondition
            break;

这是wifi的连接上后的一个处理过程,整个过程就不好讲了,我就说下这个地方,当wifi连接成功因为mLastWifiSignalLevel初始化是-1,如mLastWifiSignalLevel没有发生变化信号强度就只会显示一格,如果没有连接上wifi信号显示图标是不可见的。mService.setIconVisibility("wifi", false);这个将图标设置为不可见状态。

mLastWifiSignalLevel在哪里会变化了,我们找到updateWifi这个函数,里面有这样一段代码:

 else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
            int iconId;
            final int newRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
            int newSignalLevel = WifiManager.calculateSignalLevel(newRssi,
                                                                  sWifiSignalImages[0].length);
            if (newSignalLevel != mLastWifiSignalLevel) {
                mLastWifiSignalLevel = newSignalLevel;
                if (mIsWifiConnected) {
                    iconId = sWifiSignalImages[mInetCondition][newSignalLevel];
                } else {
                    iconId = sWifiTemporarilyNotConnectedImage;
                }
                mService.setIcon("wifi", iconId, 0);
            }
        }

这个会改变mLastWifiSignalLevel同时也会更新wifi信号图标.

而updateWifi就是在onReceive里被调用,代码如下:

            else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION) ||
                    action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION) ||
                    action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
                updateWifi(intent);
            }

当有这三个广播的时候才会执行updateWifi,就是说当有RSSI_CHANGED_ACTION时,信号显示图标才会发生变化,但是我把打印信息打开发现,没有这个广播产生。所以我又想到会不会是HAL层的问题,于是我又看了下HAL层,基本函数是差不多的,主要返回的相关信息应该是在这个函数里面:

int wifi_send_command(struct wpa_ctrl *ctrl, const char *cmd, char *reply, size_t *reply_len)
{
    int ret;

    if (ctrl_conn == NULL) {
        LOGV("Not connected to wpa_supplicant - \"%s\" command dropped.\n", cmd);
        return -1;
    }
    ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), reply, reply_len, NULL);
    if (ret == -2) {
        LOGD("'%s' command timed out.\n", cmd);
        return -2;
    } else if (ret < 0 || strncmp(reply, "FAIL", 4) == 0) {
        return -1;
    }
    if (strncmp(cmd, "PING", 4) == 0) {
        reply[*reply_len] = '\0';
    }
    return 0;
}

加上打印信息,发现wpa根本就没有发生获取信号的命令,问题终于找到了。

wpa的源码在external/wpa_supplicant中发送命令给HAL层是在driver_wext.c中的wpa_driver_priv_driver_cmd函数中,具体修改如下:

sdio 8686将此函数修改为:

static int wpa_driver_priv_driver_cmd(void *priv, char *cmd, char *buf, size_t buf_len)
{
	struct wpa_driver_wext_data *drv = priv;
	int ret = -1;

	wpa_printf(MSG_DEBUG, "%s %s", __func__, cmd);

	if (os_strcasecmp(cmd, "start") == 0) {
		wpa_printf(MSG_DEBUG,"Start command");
		return (ret);
	}

	if (os_strcasecmp(cmd, "stop") == 0) {
		wpa_printf(MSG_DEBUG,"Stop command");
	}
	else if (os_strcasecmp(cmd, "macaddr") == 0) {
		struct ifreq ifr;
		os_memset(&ifr, 0, sizeof(ifr));
		os_strncpy(ifr.ifr_name, drv->ifname, IFNAMSIZ);

		if (ioctl(drv->ioctl_sock, SIOCGIFHWADDR, &ifr) < 0) {
			perror("ioctl[SIOCGIFHWADDR]");
			ret = -1;
		} else {
			u8 *macaddr = (u8 *) ifr.ifr_hwaddr.sa_data;
			ret = snprintf(buf, buf_len, "Macaddr = " MACSTR "\n",
			               MAC2STR(macaddr));
		}
	}
	else if (os_strcasecmp(cmd, "scan-passive") == 0) {
		wpa_printf(MSG_DEBUG,"Scan Passive command");
	}
	else if (os_strcasecmp(cmd, "scan-active") == 0) {
		wpa_printf(MSG_DEBUG,"Scan Active command");
	}
	else if (os_strcasecmp(cmd, "linkspeed") == 0) {
		wpa_printf(MSG_DEBUG,"Link Speed command");
	}
	else if (os_strncasecmp(cmd, "scan-channels", 13) == 0) {
	}
#if	0	//add by dao
	else if (os_strcasecmp(cmd, "rssi") == 0) {
#else
	else if ((os_strcasecmp(cmd, "rssi") == 0) || (os_strcasecmp(cmd, "rssi-approx") == 0)){
#endif
		struct iwreq wrq;
		struct iw_statistics stats;
		signed int rssi;

		wrq.u.data.pointer = (caddr_t) &stats;
		wrq.u.data.length = sizeof(stats);
		wrq.u.data.flags = 1; /* Clear updated flag */
		strncpy(wrq.ifr_name, drv->ifname, IFNAMSIZ);

		if (ioctl(drv->ioctl_sock, SIOCGIWSTATS, &wrq) < 0) {
			perror("ioctl[SIOCGIWSTATS]");
			ret = -1;
		} else {
#if	0 //add by dao
			stats.qual.updated |= IW_QUAL_DBM;
#endif
			if (stats.qual.updated & IW_QUAL_DBM) {
				/* Values in dBm, stored in u8 with range 63 : -192 */
				rssi = ( stats.qual.level > 63 ) ?
					stats.qual.level - 0x100 :
					stats.qual.level;
			} else {
				rssi = stats.qual.level;
			}

			if (drv->ssid_len != 0 && drv->ssid_len < buf_len) {
				os_memcpy((void *) buf, (void *) (drv->ssid),
						drv->ssid_len );
				ret = drv->ssid_len;
				ret += snprintf(&buf[ret], buf_len-ret,
						" rssi %d\n", rssi);
				if (ret < (int)buf_len) {
					return( ret );
				}
				ret = -1;
			}
		}
	}
	else if (os_strncasecmp(cmd, "powermode", 9) == 0) {
	}
	else if (os_strncasecmp(cmd, "getpower", 8) == 0) {
	}
	else if (os_strncasecmp(cmd, "get-rts-threshold", 17) == 0) {
		struct iwreq wrq;
		unsigned int rtsThreshold;

		strncpy(wrq.ifr_name, drv->ifname, IFNAMSIZ);

		if (ioctl(drv->ioctl_sock, SIOCGIWRTS, &wrq) < 0) {
			perror("ioctl[SIOCGIWRTS]");
			ret = -1;
		} else {
			rtsThreshold = wrq.u.rts.value;
			wpa_printf(MSG_DEBUG,"Get RTS Threshold command = %d",
				rtsThreshold);
			ret = snprintf(buf, buf_len, "rts-threshold = %u\n",
				rtsThreshold);
			if (ret < (int)buf_len) {
				return( ret );
			}
		}
	}
	else if (os_strncasecmp(cmd, "set-rts-threshold", 17) == 0) {
		struct iwreq wrq;
		unsigned int rtsThreshold;
		char *cp = cmd + 17;
		char *endp;

		strncpy(wrq.ifr_name, drv->ifname, IFNAMSIZ);

		if (*cp != '\0') {
			rtsThreshold = (unsigned int)strtol(cp, &endp, 0);
			if (endp != cp) {
				wrq.u.rts.value = rtsThreshold;
				wrq.u.rts.fixed = 1;
				wrq.u.rts.disabled = 0;

				if (ioctl(drv->ioctl_sock, SIOCSIWRTS, &wrq) < 0) {
					perror("ioctl[SIOCGIWRTS]");
					ret = -1;
				} else {
					rtsThreshold = wrq.u.rts.value;
					wpa_printf(MSG_DEBUG,"Set RTS Threshold command = %d", rtsThreshold);
					ret = 0;
				}
			}
		}
	}
	else if (os_strcasecmp(cmd, "btcoexscan-start") == 0) {
	}
	else if (os_strcasecmp(cmd, "btcoexscan-stop") == 0) {
	}
	else if (os_strcasecmp(cmd, "rxfilter-start") == 0) {
		wpa_printf(MSG_DEBUG,"Rx Data Filter Start command");
	}
	else if (os_strcasecmp(cmd, "rxfilter-stop") == 0) {
		wpa_printf(MSG_DEBUG,"Rx Data Filter Stop command");
	}
	else if (os_strcasecmp(cmd, "rxfilter-statistics") == 0) {
	}
	else if (os_strncasecmp(cmd, "rxfilter-add", 12) == 0 ) {
	}
	else if (os_strncasecmp(cmd, "rxfilter-remove",15) == 0) {
	}
	else if (os_strcasecmp(cmd, "snr") == 0) {
		struct iwreq wrq;
		struct iw_statistics stats;
		int snr, rssi, noise;

		wrq.u.data.pointer = (caddr_t) &stats;
		wrq.u.data.length = sizeof(stats);
		wrq.u.data.flags = 1; /* Clear updated flag */
		strncpy(wrq.ifr_name, drv->ifname, IFNAMSIZ);

		if (ioctl(drv->ioctl_sock, SIOCGIWSTATS, &wrq) < 0) {
			perror("ioctl[SIOCGIWSTATS]");
			ret = -1;
		} else {
				stats.qual.updated |= IW_QUAL_DBM;
			if (stats.qual.updated & IW_QUAL_DBM) {
				/* Values in dBm, stored in u8 with range 63 : -192 */
				rssi = ( stats.qual.level > 63 ) ?
					stats.qual.level - 0x100 :
					stats.qual.level;
				noise = ( stats.qual.noise > 63 ) ?
					stats.qual.noise - 0x100 :
					stats.qual.noise;
			} else {
				rssi = stats.qual.level;
				noise = stats.qual.noise;
			}

			snr = rssi - noise;

			ret = snprintf(buf, buf_len, "snr = %u\n", (unsigned int)snr);
			if (ret < (int)buf_len) {
				return( ret );
			}
		}
	}
	else if (os_strncasecmp(cmd, "btcoexmode", 10) == 0) {
	}
	else if( os_strcasecmp(cmd, "btcoexstat") == 0 ) {
	}
	else {
		wpa_printf(MSG_DEBUG,"Unsupported command");
	}
	return (ret);
}

rtl8192cu修改为如下:

static int wpa_driver_priv_driver_cmd(void *priv, char *cmd, char *buf, size_t buf_len)
{
	struct wpa_driver_wext_data *drv = priv;
	struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(drv->ctx);
	struct iwreq iwr;
	int ret = 0, flags;

	wpa_printf(MSG_DEBUG, "%s %s len = %d", __func__, cmd, buf_len);

	if (os_strcasecmp(cmd, "RSSI-APPROX") == 0) {
		os_strncpy(cmd, "RSSI", MAX_DRV_CMD_SIZE);
	}
	else if( os_strncasecmp(cmd, "SCAN-CHANNELS", 13) == 0 ) {
		int no_of_chan;

		no_of_chan = atoi(cmd + 13);
		os_snprintf(cmd, MAX_DRV_CMD_SIZE, "COUNTRY %s",
			wpa_driver_get_country_code(no_of_chan));
	}
	else if (os_strcasecmp(cmd, "STOP") == 0) {
		if ((wpa_driver_wext_get_ifflags(drv, &flags) == 0) &&
		    (flags & IFF_UP)) {
			wpa_printf(MSG_ERROR, "WEXT: %s when iface is UP", cmd);
			wpa_driver_wext_set_ifflags(drv, flags & ~IFF_UP);
		}
	}
	else if( os_strcasecmp(cmd, "RELOAD") == 0 ) {
		wpa_printf(MSG_DEBUG,"Reload command");
		wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
		return ret;
	}

	os_memset(&iwr, 0, sizeof(iwr));
	os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
	os_memcpy(buf, cmd, strlen(cmd) + 1);
	iwr.u.data.pointer = buf;
	iwr.u.data.length = buf_len;

	if ((ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr)) < 0) {
		perror("ioctl[SIOCSIWPRIV]");
	}

	if (ret < 0) {
		wpa_printf(MSG_ERROR, "%s failed", __func__);
		drv->errors++;
		if (drv->errors > WEXT_NUMBER_SEQUENTIAL_ERRORS) {
			drv->errors = 0;
			wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
		}
	}
	else {
		drv->errors = 0;
		ret = 0;
		if ((os_strcasecmp(cmd, "RSSI") == 0) ||
		    (os_strcasecmp(cmd, "LINKSPEED") == 0) ||
		    (os_strcasecmp(cmd, "MACADDR") == 0)) {
			ret = strlen(buf);
		}
/*		else if (os_strcasecmp(cmd, "START") == 0) {
			os_sleep(0, WPA_DRIVER_WEXT_WAIT_US);
			wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED");
		}
		else if (os_strcasecmp(cmd, "STOP") == 0) {
			wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED");
		}*/
		wpa_printf(MSG_DEBUG, "%s %s len = %d, %d", __func__, buf, ret, strlen(buf));
	}
	return ret;
}

重新编译wpa后,安装系统,结果正常,statusbar与settting中的信号显示都正常了。还有一些没有说清楚的地方,有空在研究。

【上篇】
【下篇】

抱歉!评论已关闭.