summaryrefslogtreecommitdiffstats
path: root/service/jni
diff options
context:
space:
mode:
authorSravanthi Palakonda <srapal@codeaurora.org>2015-07-27 16:38:09 +0530
committerLinux Build Service Account <lnxbuild@localhost>2015-10-06 03:20:30 -0600
commit1a0319f2c6766a93090565d091ba13cf124f8590 (patch)
treea396fe5ba2f8c03e793e03be86b0f2a242225611 /service/jni
parent4e0e33db7f18f3b0a5206c2957ae6c702f9b7f4f (diff)
downloadandroid_frameworks_opt_net_wifi-1a0319f2c6766a93090565d091ba13cf124f8590.tar.gz
android_frameworks_opt_net_wifi-1a0319f2c6766a93090565d091ba13cf124f8590.tar.bz2
android_frameworks_opt_net_wifi-1a0319f2c6766a93090565d091ba13cf124f8590.zip
wifi: Support for AP with Chinese GBK Charset SSID
It doesn't support Chinese GBK Charset in original Android. But there are some APs with Chinese GBK Charset SSID, it will result in that wifi can't display these APs nomally and connect to these APs. Here make a conversion in wifi JNI layer. When "SCAN" or "GET_NETWORK" command has the reply with Chinese GBK Charset SSID, convert GBK to UTF-8. Change-Id: Iaf01a0e44e8ad610408f1533723fc668c5a764b0
Diffstat (limited to 'service/jni')
-rw-r--r--service/jni/COPYING22
-rw-r--r--service/jni/README56
-rw-r--r--service/jni/com_android_server_wifi_Gbk2Utf.cpp577
-rw-r--r--service/jni/com_android_server_wifi_Gbk2Utf.h56
-rw-r--r--service/jni/com_android_server_wifi_WifiNative.cpp71
5 files changed, 777 insertions, 5 deletions
diff --git a/service/jni/COPYING b/service/jni/COPYING
new file mode 100644
index 000000000..8a98582c8
--- /dev/null
+++ b/service/jni/COPYING
@@ -0,0 +1,22 @@
+wpa_supplicant and hostapd
+--------------------------
+
+Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> and contributors
+All Rights Reserved.
+
+
+See the README file for the current license terms.
+
+This software was previously distributed under BSD/GPL v2 dual license
+terms that allowed either of those license alternatives to be
+selected. As of February 11, 2012, the project has chosen to use only
+the BSD license option for future distribution. As such, the GPL v2
+license option is no longer used. It should be noted that the BSD
+license option (the one with advertisement clause removed) is compatible
+with GPL and as such, does not prevent use of this software in projects
+that use GPL.
+
+Some of the files may still include pointers to GPL version 2 license
+terms. However, such copyright and license notifications are maintained
+only for attribution purposes and any distribution of this software
+after February 11, 2012 is no longer under the GPL v2 option.
diff --git a/service/jni/README b/service/jni/README
new file mode 100644
index 000000000..8de14a64f
--- /dev/null
+++ b/service/jni/README
@@ -0,0 +1,56 @@
+wpa_supplicant and hostapd
+--------------------------
+
+Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi> and contributors
+All Rights Reserved.
+
+These programs are licensed under the BSD license (the one with
+advertisement clause removed).
+
+If you are submitting changes to the project, please see CONTRIBUTIONS
+file for more instructions.
+
+
+This package may include either wpa_supplicant, hostapd, or both. See
+README file respective subdirectories (wpa_supplicant/README or
+hostapd/README) for more details.
+
+Source code files were moved around in v0.6.x releases and compared to
+earlier releases, the programs are now built by first going to a
+subdirectory (wpa_supplicant or hostapd) and creating build
+configuration (.config) and running 'make' there (for Linux/BSD/cygwin
+builds).
+
+
+License
+-------
+
+This software may be distributed, used, and modified under the terms of
+BSD license:
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+3. Neither the name(s) of the above-listed copyright holder(s) nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/service/jni/com_android_server_wifi_Gbk2Utf.cpp b/service/jni/com_android_server_wifi_Gbk2Utf.cpp
new file mode 100644
index 000000000..194b44660
--- /dev/null
+++ b/service/jni/com_android_server_wifi_Gbk2Utf.cpp
@@ -0,0 +1,577 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * wpa_supplicant/hostapd / common helper functions, etc.
+ * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#define LOG_TAG "wifi_gbk2utf"
+
+#include "jni.h"
+#include "com_android_server_wifi_Gbk2Utf.h"
+
+#define BUF_SIZE 256
+#define CONVERT_LINE_LEN 2048
+#define CHARSET_CN ("gbk")
+
+namespace android {
+
+static jint DBG = false;
+
+struct accessPointObjectItem *g_pItemList = NULL;
+struct accessPointObjectItem *g_pLastNode = NULL;
+pthread_mutex_t *g_pItemListMutex = NULL;
+
+static void addAPObjectItem(const char *ssid, const char *ssid_utf8)
+{
+ if (NULL == ssid || NULL == ssid_utf8) {
+ ALOGE("ssid or ssid_utf8 is NULL");
+ return;
+ }
+
+ struct accessPointObjectItem *pTmpItemNode = NULL;
+ struct accessPointObjectItem *pItemNode = NULL;
+ bool foundItem = false;
+
+ pthread_mutex_lock(g_pItemListMutex);
+ pTmpItemNode = g_pItemList;
+ while (pTmpItemNode) {
+ if (pTmpItemNode->ssid && (*(pTmpItemNode->ssid) == ssid)) {
+ foundItem = true;
+ break;
+ }
+ pTmpItemNode = pTmpItemNode->pNext;
+ }
+ if (foundItem) {
+ if (DBG)
+ ALOGD("Found AP %s", pTmpItemNode->ssid->string());
+ } else {
+ pItemNode = new struct accessPointObjectItem();
+ if (NULL == pItemNode) {
+ ALOGE("Failed to allocate memory for new item!");
+ goto EXIT;
+ }
+ memset(pItemNode, 0, sizeof(accessPointObjectItem));
+ pItemNode->ssid_utf8 = new String8(ssid_utf8);
+ if (NULL == pItemNode->ssid_utf8) {
+ ALOGE("Failed to allocate memory for new ssid_utf8!");
+ delete pItemNode;
+ goto EXIT;
+ }
+ pItemNode->ssid = new String8(ssid);
+ if (NULL == pItemNode->ssid) {
+ ALOGE("Failed to allocate memory for new ssid!");
+ delete pItemNode;
+ goto EXIT;
+ }
+
+ pItemNode->pNext = NULL;
+ if (DBG)
+ ALOGD("AP doesn't exist, new one for %s", ssid);
+ if (NULL == g_pItemList) {
+ g_pItemList = pItemNode;
+ g_pLastNode = g_pItemList;
+ } else {
+ g_pLastNode->pNext = pItemNode;
+ g_pLastNode = pItemNode;
+ }
+ }
+
+EXIT:
+ pthread_mutex_unlock(g_pItemListMutex);
+}
+
+static int hex2num(char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ return -1;
+}
+
+
+static int hex2byte(const char *hex)
+{
+ int a, b;
+ a = hex2num(*hex++);
+ if (a < 0)
+ return -1;
+ b = hex2num(*hex++);
+ if (b < 0)
+ return -1;
+ return (a << 4) | b;
+}
+
+/* parse SSID string encoded from wpa_supplicant to normal string */
+static size_t ssid_decode(char *buf, size_t maxlen, const char *str)
+{
+ const char *pos = str;
+ size_t len = 0;
+ int val;
+
+ while (*pos) {
+ if (len == maxlen)
+ break;
+ switch (*pos) {
+ case '\\':
+ pos++;
+ switch (*pos) {
+ case '\\':
+ buf[len++] = '\\';
+ pos++;
+ break;
+ case '"':
+ buf[len++] = '"';
+ pos++;
+ break;
+ case 'n':
+ buf[len++] = '\n';
+ pos++;
+ break;
+ case 'r':
+ buf[len++] = '\r';
+ pos++;
+ break;
+ case 't':
+ buf[len++] = '\t';
+ pos++;
+ break;
+ case 'e':
+ buf[len++] = '\e';
+ pos++;
+ break;
+ case 'x':
+ pos++;
+ val = hex2byte(pos);
+ if (val < 0) {
+ val = hex2num(*pos);
+ if (val < 0)
+ break;
+ buf[len++] = val;
+ pos++;
+ } else {
+ buf[len++] = val;
+ pos += 2;
+ }
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ val = *pos++ - '0';
+ if (*pos >= '0' && *pos <= '7')
+ val = val * 8 + (*pos++ - '0');
+ if (*pos >= '0' && *pos <= '7')
+ val = val * 8 + (*pos++ - '0');
+ buf[len++] = val;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ buf[len++] = *pos++;
+ break;
+ }
+ }
+
+ return len;
+}
+
+/* This function can be used to convert SSIDs into printable form. Since wifi
+ * framework layer needs to parse printable form string.
+*/
+static void ssid_encode(char *txt, size_t maxlen, const char *data, unsigned int len)
+{
+ char *end = txt + maxlen;
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ if (txt + 4 > end)
+ break;
+
+ switch (data[i]) {
+ case '\"':
+ *txt++ = '\\';
+ *txt++ = '\"';
+ break;
+ case '\\':
+ *txt++ = '\\';
+ *txt++ = '\\';
+ break;
+ case '\e':
+ *txt++ = '\\';
+ *txt++ = 'e';
+ break;
+ case '\n':
+ *txt++ = '\\';
+ *txt++ = 'n';
+ break;
+ case '\r':
+ *txt++ = '\\';
+ *txt++ = 'r';
+ break;
+ case '\t':
+ *txt++ = '\\';
+ *txt++ = 't';
+ break;
+ default:
+ if (data[i] >= 32 && data[i] <= 127) {
+ *txt++ = data[i];
+ } else {
+ txt += snprintf(txt, end - txt, "\\x%02x",
+ data[i]);
+ }
+ break;
+ }
+ }
+ *txt = '\0';
+}
+
+/* check if the SSID string is UTF coded */
+static bool isUTF8String(const char* str, long length)
+{
+ unsigned int nBytes = 0;
+ unsigned char chr;
+ bool bAllAscii = true;
+ for (int i = 0; i < length; i++) {
+ chr = *(str+i);
+ if ((chr & 0x80) != 0) {
+ bAllAscii = false;
+ }
+ if (0 == nBytes) {
+ if (chr >= 0x80) {
+ if (chr >= 0xFC && chr <= 0xFD) {
+ nBytes = 6;
+ } else if (chr >= 0xF8) {
+ nBytes = 5;
+ } else if (chr >= 0xF0) {
+ nBytes = 4;
+ } else if (chr >= 0xE0) {
+ nBytes = 3;
+ } else if (chr >= 0xC0) {
+ nBytes = 2;
+ } else {
+ return false;
+ }
+ nBytes--;
+ }
+ } else {
+ if ((chr & 0xC0) != 0x80) {
+ return false;
+ }
+ nBytes--;
+ }
+ }
+
+ if (nBytes > 0 || bAllAscii) {
+ return false;
+ }
+ return true;
+}
+
+static void createFromHex(char *buf, int maxlen, const char *str)
+{
+ const char *pos = str;
+ int len = 0;
+ int val;
+
+ while(*pos){
+ if (len == maxlen)
+ break;
+ val = hex2byte(pos);
+ if (val < 0) {
+ val = hex2num(*pos);
+ if (val < 0)
+ break;
+ buf[len++] = val;
+ } else {
+ buf[len++] = val;
+ pos += 2;
+ }
+ }
+}
+
+static size_t createToHex(char *buf, size_t buf_size, const char *str, unsigned int len)
+{
+ size_t i;
+ char *pos = buf, *end = buf + buf_size;
+ int ret;
+ if (buf_size == 0)
+ return 0;
+ for (i = 0; i < len; i++) {
+ ret = snprintf(pos, end - pos, "%02x", str[i]);
+ if (ret < 0 || ret >= end - pos) {
+ end[-1] = '\0';
+ return pos - buf;
+ }
+ pos += ret;
+ }
+ end[-1] = '\0';
+ return pos - buf;
+}
+
+void parseScanResults(String16& str, const char *reply)
+{
+ unsigned int lineBeg = 0, lineEnd = 0;
+ size_t replyLen = strlen(reply);
+ char *pos = NULL;
+ char ssid[BUF_SIZE] = {0};
+ char ssid_utf8[BUF_SIZE] = {0};
+ char ssid_txt[BUF_SIZE] = {0};
+ bool isUTF8 = false, isCh = false;
+ char buf[BUF_SIZE] = {0};
+ String8 line;
+
+ UConverterType conType = UCNV_UTF8;
+ char dest[CONVERT_LINE_LEN] = {0};
+ UErrorCode err = U_ZERO_ERROR;
+ UConverter* pConverter = ucnv_open(CHARSET_CN, &err);
+ if (U_FAILURE(err)) {
+ ALOGE("ucnv_open error");
+ return;
+ }
+
+ /* Parse every line of the reply to construct accessPointObjectItem list */
+ for (lineBeg = 0, lineEnd = 0; lineEnd <= replyLen; ++lineEnd) {
+ if (lineEnd == replyLen || '\n' == reply[lineEnd]) {
+ line.setTo(reply + lineBeg, lineEnd - lineBeg + 1);
+ if (DBG)
+ ALOGD("%s, line=%s ", __FUNCTION__, line.string());
+ if (strncmp(line.string(), "ssid=", 5) == 0) {
+ sscanf(line.string() + 5, "%[^\n]", ssid);
+ ssid_decode(buf,BUF_SIZE,ssid);
+ isUTF8 = isUTF8String(buf,sizeof(buf));
+ isCh = false;
+ for (pos = buf; '\0' != *pos; pos++) {
+ if (0x80 == (*pos & 0x80)) {
+ isCh = true;
+ break;
+ }
+ }
+ if (DBG)
+ ALOGD("%s, ssid = %s, buf = %s,isUTF8= %d, isCh = %d",
+ __FUNCTION__, ssid, buf ,isUTF8, isCh);
+ if (!isUTF8 && isCh) {
+ ucnv_toAlgorithmic(conType, pConverter, dest, CONVERT_LINE_LEN,
+ buf, strlen(buf), &err);
+ if (U_FAILURE(err)) {
+ ALOGE("ucnv_toUChars error");
+ goto EXIT;
+ }
+ ssid_encode(ssid_txt, BUF_SIZE, dest, strlen(dest));
+ if (DBG)
+ ALOGD("%s, ssid_txt = %s", __FUNCTION__,ssid_txt);
+ str += String16("ssid=");
+ str += String16(ssid_txt);
+ str += String16("\n");
+ memset(ssid_utf8, 0, BUF_SIZE);
+ strlcpy(ssid_utf8, dest, BUF_SIZE);
+ memset(dest, 0, CONVERT_LINE_LEN);
+ memset(ssid_txt, 0, BUF_SIZE);
+ } else {
+ memset(buf, 0, BUF_SIZE);
+ str += String16(line.string());
+ }
+ } else if (strncmp(line.string(), "====", 4) == 0) {
+ if (DBG)
+ ALOGD("After sscanf,ssid:%s, isCh:%d",
+ ssid, isCh);
+ if( !isUTF8 && isCh){
+ addAPObjectItem(buf, ssid_utf8);
+ memset(buf, 0, BUF_SIZE);
+ }
+ }
+ if (strncmp(line.string(), "ssid=", 5) != 0)
+ str += String16(line.string());
+ lineBeg = lineEnd + 1;
+ }
+ }
+
+EXIT:
+ ucnv_close(pConverter);
+}
+
+void constructSsid(String16& str, const char *reply)
+{
+ size_t replyLen = strlen(reply);
+ char ssid[BUF_SIZE] = {0};
+ char buf[BUF_SIZE] = {0};
+ char ssid_txt[BUF_SIZE] ={0};
+ char *pos = NULL;
+ bool isUTF8 = false, isCh = false;
+
+ char dest[CONVERT_LINE_LEN] = {0};
+ UConverterType conType = UCNV_UTF8;
+ UErrorCode err = U_ZERO_ERROR;
+ UConverter* pConverter = ucnv_open(CHARSET_CN, &err);
+ if (U_FAILURE(err)) {
+ ALOGE("ucnv_open error");
+ return;
+ }
+ sscanf(reply, "%[^\n]", ssid);
+ if (DBG)
+ ALOGD("%s, ssid = %s", __FUNCTION__, ssid);
+ createFromHex(buf, BUF_SIZE, ssid);
+ isUTF8 = isUTF8String(buf, sizeof(buf));
+ isCh = false;
+ for (pos = buf; '\0' != *pos; pos++) {
+ if (0x80 == (*pos & 0x80)) {
+ isCh = true;
+ break;
+ }
+ }
+ if (!isUTF8 && isCh) {
+ ucnv_toAlgorithmic(conType, pConverter, dest, CONVERT_LINE_LEN,
+ buf, strlen(buf), &err);
+ if (U_FAILURE(err)) {
+ ALOGE("ucnv_toUChars error");
+ goto EXIT;
+ }
+ createToHex(ssid_txt, strlen(dest)*2 + 1, dest, strlen(dest));
+ if (DBG)
+ ALOGD("%s, ssid_txt = %s, dest = %s \n" ,
+ __FUNCTION__, ssid_txt, dest);
+ str += String16(ssid_txt);
+ str += String16("\n");
+ memset(dest, 0, CONVERT_LINE_LEN);
+ memset(buf, 0, BUF_SIZE);
+ memset(ssid_txt, 0, BUF_SIZE);
+ } else {
+ memset(buf, 0, BUF_SIZE);
+ str += String16(reply);
+ }
+
+EXIT:
+ ucnv_close(pConverter);
+}
+
+jboolean setNetworkVariable(char *buf)
+{
+ struct accessPointObjectItem *pTmpItemNode = NULL;
+ char pos[BUF_SIZE] = {0};
+ bool isCh = false;
+ bool gbk_found = false;
+ int i;
+
+ unsigned int netId;
+ char name[BUF_SIZE] = {0};
+ char value[BUF_SIZE] = {0};
+ char interface[BUF_SIZE] = {0};
+ char dummy[BUF_SIZE] = {0};
+ char ssid[BUF_SIZE] = {0};
+ size_t utf8_len = 0;
+ if (strnlen(buf, BUF_SIZE) == BUF_SIZE) {
+ ALOGE("setNetworkVariable failed due to invalid length");
+ return JNI_FALSE;
+ }
+
+ /* parse SET_NETWORK command*/
+ sscanf(buf, "%s %s %d %s %s", interface, dummy, &netId, name, value);
+
+ /* L Framework will convert string to HEX, so we convert it back here for comparation */
+ if (0 == strncmp(name, "ssid", 4)) {
+ createFromHex(ssid, BUF_SIZE, value);
+ }
+
+ if (DBG)
+ ALOGD("parse SET_NETWORK command success, netId = %d, name = %s, value =%s, length=%d",
+ netId, name, value, strlen(value));
+
+ pthread_mutex_lock(g_pItemListMutex);
+ pTmpItemNode = g_pItemList;
+ if (NULL == pTmpItemNode) {
+ ALOGE("g_pItemList is NULL");
+ }
+ while (pTmpItemNode) {
+ if (pTmpItemNode->ssid_utf8) {
+ ALOGD("ssid_utf8 = %s, length=%d, value =%s, length=%d",
+ pTmpItemNode->ssid_utf8->string(),strlen(pTmpItemNode->ssid_utf8->string()), ssid, strlen(ssid));
+
+ if (0 == strcmp(pTmpItemNode->ssid_utf8->string(), ssid)) {
+ gbk_found = true;
+ break;
+ }
+ }
+ pTmpItemNode = pTmpItemNode->pNext;
+ }
+
+ if (0 == strncmp(name, "ssid", 4) && gbk_found) {
+ snprintf(buf, BUF_SIZE, "%s SET_NETWORK %d ssid \"%s\"", interface, netId, pTmpItemNode->ssid->string());
+ if (DBG)
+ ALOGD("new SET_NETWORK command is: %s", buf);
+ }
+
+ pthread_mutex_unlock(g_pItemListMutex);
+
+
+ return JNI_TRUE;
+}
+
+void constructEventSsid(char *eventstr)
+{
+ char *pos = NULL;
+ char *tmp = NULL;
+ char ssid[BUF_SIZE] = {0};
+ char ssid_txt[BUF_SIZE] = {0};
+ char buf[BUF_SIZE] = {0};
+ bool isUTF8 = false, isCh = false;
+
+ UConverterType conType = UCNV_UTF8;
+ char dest[CONVERT_LINE_LEN] = {0};
+ UErrorCode err = U_ZERO_ERROR;
+ UConverter* pConverter = ucnv_open(CHARSET_CN, &err);
+ if (U_FAILURE(err)) {
+ ALOGE("ucnv_open error");
+ return;
+ }
+
+ tmp = strstr(eventstr, " SSID");
+ if (tmp&&(strlen(tmp) > 6 )) {
+ if(!strstr(tmp,"="))
+ sscanf(tmp + 7, "%[^\']", ssid);
+ else
+ sscanf(tmp + 6, "%s", ssid);
+ if (DBG)
+ ALOGD("%s, SSID = %s", __FUNCTION__, ssid);
+ ssid_decode(buf,BUF_SIZE,ssid);
+ isUTF8 = isUTF8String(buf,sizeof(buf));
+ isCh = false;
+ for (pos = buf; '\0' != *pos; pos++) {
+ if (0x80 == (*pos & 0x80)) {
+ isCh = true;
+ break;
+ }
+ }
+ if (!isUTF8 && isCh) {
+ ucnv_toAlgorithmic(conType, pConverter, dest, CONVERT_LINE_LEN,
+ buf, strlen(buf), &err);
+ if (U_FAILURE(err)) {
+ ALOGE("ucnv_toUChars error");
+ goto EXIT;
+ }
+ ssid_encode(ssid_txt, BUF_SIZE, dest, strlen(dest));
+ if (!strstr(tmp,"="))
+ snprintf(eventstr + (strlen(eventstr) - strlen(tmp)), strlen(eventstr), " SSID \'%s\'", ssid_txt);
+ else
+ snprintf(eventstr + (strlen(eventstr) - strlen(tmp)), strlen(eventstr), " SSID=%s", ssid_txt);
+ if (DBG)
+ ALOGD("%s, ssid_txt = %s, eventsrt = %s", __FUNCTION__, ssid_txt, eventstr);
+ }
+ }
+
+EXIT:
+ ucnv_close(pConverter);
+}
+
+} //namespace android
diff --git a/service/jni/com_android_server_wifi_Gbk2Utf.h b/service/jni/com_android_server_wifi_Gbk2Utf.h
new file mode 100644
index 000000000..37e7a2b75
--- /dev/null
+++ b/service/jni/com_android_server_wifi_Gbk2Utf.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <utils/String8.h>
+#include <utils/String16.h>
+#include <pthread.h>
+#include <unicode/ucnv.h>
+#include <unicode/ucsdet.h>
+#include <net/if.h>
+#include <sys/socket.h>
+#include <linux/wireless.h>
+#include <utils/misc.h>
+#include <utils/Log.h>
+
+namespace android {
+
+struct accessPointObjectItem {
+ String8 *ssid_utf8;
+ String8 *ssid;
+ struct accessPointObjectItem *pNext;
+};
+
+extern void parseScanResults(String16& str, const char *reply);
+
+extern void constructSsid(String16& str, const char *reply);
+
+extern void constructEventSsid(char *eventstr);
+
+extern jboolean setNetworkVariable(char *buf);
+
+} //namespace android
diff --git a/service/jni/com_android_server_wifi_WifiNative.cpp b/service/jni/com_android_server_wifi_WifiNative.cpp
index 3c7270a94..a2912a9bb 100644
--- a/service/jni/com_android_server_wifi_WifiNative.cpp
+++ b/service/jni/com_android_server_wifi_WifiNative.cpp
@@ -20,10 +20,10 @@
#include "JniConstants.h"
#include <ScopedUtfChars.h>
#include <ScopedBytes.h>
-#include <utils/misc.h>
+//#include <utils/misc.h>
#include <android_runtime/AndroidRuntime.h>
-#include <utils/Log.h>
-#include <utils/String16.h>
+//#include <utils/Log.h>
+//#include <utils/String16.h>
#include <ctype.h>
#include <sys/socket.h>
#include <linux/if.h>
@@ -35,6 +35,11 @@
#define REPLY_BUF_SIZE 4096 // wpa_supplicant's maximum size.
#define EVENT_BUF_SIZE 2048
+#define CONVERT_LINE_LEN 2048
+#define CHARSET_CN ("gbk")
+
+#include "com_android_server_wifi_Gbk2Utf.h"
+
namespace android {
static jint DBG = false;
@@ -100,13 +105,21 @@ int init_wifi_hal_func_table(wifi_hal_fn *hal_fn) {
return 0;
}
+extern struct accessPointObjectItem *g_pItemList;
+extern struct accessPointObjectItem *g_pLastNode;
+extern pthread_mutex_t *g_pItemListMutex;
+extern String8 *g_pCurrentSSID;
static bool doCommand(JNIEnv* env, jstring javaCommand,
char* reply, size_t reply_len) {
ScopedUtfChars command(env, javaCommand);
if (command.c_str() == NULL) {
return false; // ScopedUtfChars already threw on error.
}
-
+ if(strstr(command.c_str(), "SET_NETWORK")) {
+ if(!setNetworkVariable((char *)command.c_str())) {
+ return false;
+ }
+ }
if (DBG) {
ALOGD("doCommand: %s", command.c_str());
}
@@ -144,10 +157,25 @@ static jboolean doBooleanCommand(JNIEnv* env, jstring javaCommand) {
// Send a command to the supplicant, and return the reply as a String.
static jstring doStringCommand(JNIEnv* env, jstring javaCommand) {
char reply[REPLY_BUF_SIZE];
+ ScopedUtfChars command(env, javaCommand);
+ if (command.c_str() == NULL) {
+ return NULL;
+ }
if (!doCommand(env, javaCommand, reply, sizeof(reply))) {
return NULL;
}
- return env->NewStringUTF(reply);
+ if (DBG) ALOGD("cmd = %s, reply: %s", command.c_str(), reply);
+ String16 str;
+ if (strstr(command.c_str(),"BSS RANGE=")) {
+ parseScanResults(str,reply);
+ } else if (strstr(command.c_str(),"GET_NETWORK") &&
+ strstr(command.c_str(),"ssid") && !strstr(command.c_str(),"bssid")
+ && !strstr(command.c_str(),"scan_ssid")){
+ constructSsid(str, reply);
+ } else {
+ str += String16((char *)reply);
+ }
+ return env->NewString((const jchar *)str.string(), str.size());
}
static jboolean android_net_wifi_isDriverLoaded(JNIEnv* env, jobject)
@@ -157,11 +185,41 @@ static jboolean android_net_wifi_isDriverLoaded(JNIEnv* env, jobject)
static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject)
{
+ g_pItemListMutex = new pthread_mutex_t;
+ if (NULL == g_pItemListMutex) {
+ ALOGE("Failed to allocate memory for g_pItemListMutex!");
+ return JNI_FALSE;
+ }
+ pthread_mutex_init(g_pItemListMutex, NULL);
return (::wifi_load_driver() == 0);
}
static jboolean android_net_wifi_unloadDriver(JNIEnv* env, jobject)
{
+ if (g_pItemListMutex != NULL) {
+ pthread_mutex_lock(g_pItemListMutex);
+ struct accessPointObjectItem *pCurrentNode = g_pItemList;
+ struct accessPointObjectItem *pNextNode = NULL;
+ while (pCurrentNode) {
+ pNextNode = pCurrentNode->pNext;
+ if (NULL != pCurrentNode->ssid) {
+ delete pCurrentNode->ssid;
+ pCurrentNode->ssid = NULL;
+ }
+ if (NULL != pCurrentNode->ssid_utf8) {
+ delete pCurrentNode->ssid_utf8;
+ pCurrentNode->ssid_utf8 = NULL;
+ }
+ delete pCurrentNode;
+ pCurrentNode = pNextNode;
+ }
+ g_pItemList = NULL;
+ g_pLastNode = NULL;
+ pthread_mutex_unlock(g_pItemListMutex);
+ pthread_mutex_destroy(g_pItemListMutex);
+ delete g_pItemListMutex;
+ g_pItemListMutex = NULL;
+ }
return (::wifi_unload_driver() == 0);
}
@@ -190,6 +248,9 @@ static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject)
char buf[EVENT_BUF_SIZE];
int nread = ::wifi_wait_for_event(buf, sizeof buf);
if (nread > 0) {
+ if (strstr(buf, " SSID=") || strstr(buf, " SSID ")){
+ constructEventSsid(buf);
+ }
return env->NewStringUTF(buf);
} else {
return NULL;