android wifi移植statusbar訊號只顯示一格的問題

來源:互聯網
上載者:User

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) {}#if0//add by daoelse if (os_strcasecmp(cmd, "rssi") == 0) {#elseelse if ((os_strcasecmp(cmd, "rssi") == 0) || (os_strcasecmp(cmd, "rssi-approx") == 0)){#endifstruct 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 {#if0 //add by daostats.qual.updated |= IW_QUAL_DBM;#endifif (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中的訊號顯示都正常了。還有一些沒有說清楚的地方,有空在研究。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.