android 와이파이 이식statusbar 신호가 한 칸만 표시되는 문제
처음에 나는 줄곧 프레임워크의 문제라고 의심했기 때문에 오랫동안 프레임워크를 연구했다.관련 코드는 아래 디렉터리에 있습니다 (android2.3)
statusbar 소스는 프레임워크/base/packages/SystemUI/src/com/android/systemui/statusbar에서
설정 중인 와이파이 부분 원본은packages/apps/Settings/src/com/android/settings/wifi에 있습니다
내가 발생한 문제는 이렇다. 와이파이가 연결된 후statusbar 위의 와이파이 신호는 항상 한 칸만 보이고 setting 안의 와이파이 신호는 때로는 한 칸을 보이고 때로는 정상적인 것을 나타낸다. 다음은 전체 과정을 간단하게 설명한다.
statusbar 원본 디렉터리에 StatusBarPolicy가 있습니다.java 파일에서 업데이트Connectivity 함수를 찾았습니다. 다음 코드를 보십시오.
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;
이것은 와이파이의 연결 후의 처리 과정이다. 전체 과정은 말하기 어렵다. 나는 이 곳을 말한다. 와이파이 연결이 성공하면 mLast 와이파이 시그널 Level이 초기화되었기 때문이다. 예를 들어 -1이다.mLastWifiSignal Level은 신호의 강도를 바꾸지 않으면 한 칸만 표시됩니다. 와이파이 신호에 연결되지 않으면 아이콘이 보이지 않습니다.mService.setIconVisibility("wifi
, false). 아이콘을 보이지 않는 상태로 설정합니다.
그럼 mLast Wifi Signal Level은 어디에서 바뀔까요? 업데이트 Wifi라는 함수를 찾았는데 그 안에 이런 코드가 있습니다.
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);
}
}
이게 바뀔 거예요.mLastWifi Signal Level은 와이파이 신호 아이콘도 업데이트합니다.
업데이트와이파이는 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);
}
이 세 개의 방송이 있을 때만 업데이트 와이파이를 실행한다. 즉, RSSICHANGED_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.
", cmd);
return -1;
}
ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), reply, reply_len, NULL);
if (ret == -2) {
LOGD("'%s' command timed out.
", 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/wpasupplicant에서 HAL 레이어에 명령을 보내는 것은 driverwext.c의 wpadriver_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 "
",
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
", 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
",
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
", (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와setting의 신호가 모두 정상적으로 나타났다.아직 분명하게 말하지 못한 부분이 있어서 틈이 나면 연구하고 있다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.