summaryrefslogtreecommitdiffstats
path: root/wifi/java
diff options
context:
space:
mode:
authorIrfan Sheriff <isheriff@google.com>2012-09-05 10:46:24 -0700
committerIrfan Sheriff <isheriff@google.com>2012-09-11 10:50:04 -0700
commitb6deeed3ceff9e0f754697987b7c724901996082 (patch)
tree790b652af7de47429fc4a92d1680d01b57a92269 /wifi/java
parent799553e02aa3350397d723982d42198a5bab774c (diff)
downloadframeworks_base-b6deeed3ceff9e0f754697987b7c724901996082.zip
frameworks_base-b6deeed3ceff9e0f754697987b7c724901996082.tar.gz
frameworks_base-b6deeed3ceff9e0f754697987b7c724901996082.tar.bz2
Handle ascii encoded SSID
Supplicant now passes as an ascii encoded string that allows it to pass any sequence of bytes for a SSID. see src/utils/common.c in supplicant for details of the implementation. We create a SSID structure WifiSsid in framework to store the ssid and handle the conversion appropriately when required for printing and for an application. At this point, we still do not handle non-printable octets from an application perspective for connectivity Bug: 7110903 Change-Id: I520e5ee23baed4867b8b408bbb3eda5c9e92b6bf
Diffstat (limited to 'wifi/java')
-rw-r--r--wifi/java/android/net/wifi/ScanResult.java35
-rw-r--r--wifi/java/android/net/wifi/StateChangeResult.java7
-rw-r--r--wifi/java/android/net/wifi/WifiConfigStore.java8
-rw-r--r--wifi/java/android/net/wifi/WifiConfiguration.java21
-rw-r--r--wifi/java/android/net/wifi/WifiInfo.java44
-rw-r--r--wifi/java/android/net/wifi/WifiMonitor.java16
-rw-r--r--wifi/java/android/net/wifi/WifiSsid.java217
-rw-r--r--wifi/java/android/net/wifi/WifiStateMachine.java18
8 files changed, 326 insertions, 40 deletions
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 3e20756..9977419 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -28,6 +28,10 @@ import android.os.Parcel;
public class ScanResult implements Parcelable {
/** The network name. */
public String SSID;
+
+ /** Ascii encoded SSID. This will replace SSID when we deprecate it. @hide */
+ public WifiSsid wifiSsid;
+
/** The address of the access point. */
public String BSSID;
/**
@@ -52,15 +56,11 @@ public class ScanResult implements Parcelable {
*/
public long timestamp;
- /**
- * We'd like to obtain the following attributes,
- * but they are not reported via the socket
- * interface, even though they are known
- * internally by wpa_supplicant.
- * {@hide}
- */
- public ScanResult(String SSID, String BSSID, String caps, int level, int frequency, long tsf) {
- this.SSID = SSID;
+ /** {@hide} */
+ public ScanResult(WifiSsid wifiSsid, String BSSID, String caps, int level, int frequency,
+ long tsf) {
+ this.wifiSsid = wifiSsid;
+ this.SSID = (wifiSsid != null) ? wifiSsid.toString() : WifiSsid.NONE;
this.BSSID = BSSID;
this.capabilities = caps;
this.level = level;
@@ -68,9 +68,11 @@ public class ScanResult implements Parcelable {
this.timestamp = tsf;
}
+
/** copy constructor {@hide} */
public ScanResult(ScanResult source) {
if (source != null) {
+ wifiSsid = source.wifiSsid;
SSID = source.SSID;
BSSID = source.BSSID;
capabilities = source.capabilities;
@@ -86,7 +88,7 @@ public class ScanResult implements Parcelable {
String none = "<none>";
sb.append("SSID: ").
- append(SSID == null ? none : SSID).
+ append(wifiSsid == null ? WifiSsid.NONE : wifiSsid).
append(", BSSID: ").
append(BSSID == null ? none : BSSID).
append(", capabilities: ").
@@ -108,7 +110,12 @@ public class ScanResult implements Parcelable {
/** Implement the Parcelable interface {@hide} */
public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(SSID);
+ if (wifiSsid != null) {
+ dest.writeInt(1);
+ wifiSsid.writeToParcel(dest, flags);
+ } else {
+ dest.writeInt(0);
+ }
dest.writeString(BSSID);
dest.writeString(capabilities);
dest.writeInt(level);
@@ -120,8 +127,12 @@ public class ScanResult implements Parcelable {
public static final Creator<ScanResult> CREATOR =
new Creator<ScanResult>() {
public ScanResult createFromParcel(Parcel in) {
+ WifiSsid wifiSsid = null;
+ if (in.readInt() == 1) {
+ wifiSsid = WifiSsid.CREATOR.createFromParcel(in);
+ }
return new ScanResult(
- in.readString(),
+ wifiSsid,
in.readString(),
in.readString(),
in.readInt(),
diff --git a/wifi/java/android/net/wifi/StateChangeResult.java b/wifi/java/android/net/wifi/StateChangeResult.java
index b15c4a6..c334b91 100644
--- a/wifi/java/android/net/wifi/StateChangeResult.java
+++ b/wifi/java/android/net/wifi/StateChangeResult.java
@@ -23,15 +23,16 @@
* @hide
*/
public class StateChangeResult {
- StateChangeResult(int networkId, String SSID, String BSSID, SupplicantState state) {
+ StateChangeResult(int networkId, WifiSsid wifiSsid, String BSSID,
+ SupplicantState state) {
this.state = state;
- this.SSID = SSID;
+ this.wifiSsid= wifiSsid;
this.BSSID = BSSID;
this.networkId = networkId;
}
int networkId;
- String SSID;
+ WifiSsid wifiSsid;
String BSSID;
SupplicantState state;
}
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index a2332e3..84506b6 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -1318,7 +1318,13 @@ class WifiConfigStore {
value = mWifiNative.getNetworkVariable(netId, WifiConfiguration.ssidVarName);
if (!TextUtils.isEmpty(value)) {
- config.SSID = value;
+ if (value.charAt(0) != '"') {
+ config.SSID = "\"" + WifiSsid.createFromHex(value).toString() + "\"";
+ //TODO: convert a hex string that is not UTF-8 decodable to a P-formatted
+ //supplicant string
+ } else {
+ config.SSID = value;
+ }
} else {
config.SSID = null;
}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 0a846fd..c4fe1b4 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -524,6 +524,27 @@ public class WifiConfiguration implements Parcelable {
}
*/
+ /** {@hide} */
+ public String getPrintableSsid() {
+ if (SSID == null) return "";
+ final int length = SSID.length();
+ if (length > 2 && (SSID.charAt(0) == '"') && SSID.charAt(length - 1) == '"') {
+ return SSID.substring(1, length - 1);
+ }
+
+ /** The ascii-encoded string format is P"<ascii-encoded-string>"
+ * The decoding is implemented in the supplicant for a newly configured
+ * network.
+ */
+ if (length > 3 && (SSID.charAt(0) == 'P') && (SSID.charAt(1) == '"') &&
+ (SSID.charAt(length-1) == '"')) {
+ WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded(
+ SSID.substring(2, length - 1));
+ return wifiSsid.toString();
+ }
+ return SSID;
+ }
+
private static BitSet readBitSet(Parcel src) {
int cardinality = src.readInt();
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 1f1cfdd..05db571 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -20,6 +20,7 @@ import android.os.Parcelable;
import android.os.Parcel;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkUtils;
+import android.text.TextUtils;
import java.net.InetAddress;
import java.net.Inet6Address;
@@ -31,6 +32,7 @@ import java.util.EnumMap;
* is in the process of being set up.
*/
public class WifiInfo implements Parcelable {
+ private static final String TAG = "WifiInfo";
/**
* This is the map described in the Javadoc comment above. The positions
* of the elements of the array must correspond to the ordinal values
@@ -57,7 +59,7 @@ public class WifiInfo implements Parcelable {
private SupplicantState mSupplicantState;
private String mBSSID;
- private String mSSID;
+ private WifiSsid mWifiSsid;
private int mNetworkId;
private boolean mHiddenSSID;
/** Received Signal Strength Indicator */
@@ -77,7 +79,7 @@ public class WifiInfo implements Parcelable {
private boolean mMeteredHint;
WifiInfo() {
- mSSID = null;
+ mWifiSsid = null;
mBSSID = null;
mNetworkId = -1;
mSupplicantState = SupplicantState.UNINITIALIZED;
@@ -94,7 +96,7 @@ public class WifiInfo implements Parcelable {
if (source != null) {
mSupplicantState = source.mSupplicantState;
mBSSID = source.mBSSID;
- mSSID = source.mSSID;
+ mWifiSsid = source.mWifiSsid;
mNetworkId = source.mNetworkId;
mHiddenSSID = source.mHiddenSSID;
mRssi = source.mRssi;
@@ -105,21 +107,34 @@ public class WifiInfo implements Parcelable {
}
}
- void setSSID(String SSID) {
- mSSID = SSID;
+ void setSSID(WifiSsid wifiSsid) {
+ mWifiSsid = wifiSsid;
// network is considered not hidden by default
mHiddenSSID = false;
}
/**
* Returns the service set identifier (SSID) of the current 802.11 network.
- * If the SSID is an ASCII string, it will be returned surrounded by double
- * quotation marks.Otherwise, it is returned as a string of hex digits. The
+ * If the SSID can be decoded as UTF-8, it will be returned surrounded by double
+ * quotation marks. Otherwise, it is returned as a string of hex digits. The
* SSID may be {@code null} if there is no network currently connected.
* @return the SSID
*/
public String getSSID() {
- return mSSID;
+ if (mWifiSsid != null) {
+ String unicode = mWifiSsid.toString();
+ if (!TextUtils.isEmpty(unicode)) {
+ return "\"" + unicode + "\"";
+ } else {
+ return mWifiSsid.getHexString();
+ }
+ }
+ return WifiSsid.NONE;
+ }
+
+ /** @hide */
+ public WifiSsid getWifiSsid() {
+ return mWifiSsid;
}
void setBSSID(String BSSID) {
@@ -279,7 +294,7 @@ public class WifiInfo implements Parcelable {
StringBuffer sb = new StringBuffer();
String none = "<none>";
- sb.append("SSID: ").append(mSSID == null ? none : mSSID).
+ sb.append("SSID: ").append(mWifiSsid == null ? WifiSsid.NONE : mWifiSsid).
append(", BSSID: ").append(mBSSID == null ? none : mBSSID).
append(", MAC: ").append(mMacAddress == null ? none : mMacAddress).
append(", Supplicant state: ").
@@ -308,7 +323,12 @@ public class WifiInfo implements Parcelable {
} else {
dest.writeByte((byte)0);
}
- dest.writeString(getSSID());
+ if (mWifiSsid != null) {
+ dest.writeInt(1);
+ mWifiSsid.writeToParcel(dest, flags);
+ } else {
+ dest.writeInt(0);
+ }
dest.writeString(mBSSID);
dest.writeString(mMacAddress);
dest.writeInt(mMeteredHint ? 1 : 0);
@@ -328,7 +348,9 @@ public class WifiInfo implements Parcelable {
info.setInetAddress(InetAddress.getByAddress(in.createByteArray()));
} catch (UnknownHostException e) {}
}
- info.setSSID(in.readString());
+ if (in.readInt() == 1) {
+ info.mWifiSsid = WifiSsid.CREATOR.createFromParcel(in);
+ }
info.mBSSID = in.readString();
info.mMacAddress = in.readString();
info.mMeteredHint = in.readInt() != 0;
diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java
index 17c930b..ab54a15 100644
--- a/wifi/java/android/net/wifi/WifiMonitor.java
+++ b/wifi/java/android/net/wifi/WifiMonitor.java
@@ -645,9 +645,12 @@ public class WifiMonitor {
* id=network-id state=new-state
*/
private void handleSupplicantStateChange(String dataString) {
- String SSID = null;
+ WifiSsid wifiSsid = null;
int index = dataString.lastIndexOf("SSID=");
- if (index != -1) SSID = dataString.substring(index + 5);
+ if (index != -1) {
+ wifiSsid = WifiSsid.createFromAsciiEncoded(
+ dataString.substring(index + 5));
+ }
String[] dataTokens = dataString.split(" ");
String BSSID = null;
@@ -690,7 +693,7 @@ public class WifiMonitor {
if (newSupplicantState == SupplicantState.INVALID) {
Log.w(TAG, "Invalid supplicant state: " + newState);
}
- notifySupplicantStateChange(networkId, SSID, BSSID, newSupplicantState);
+ notifySupplicantStateChange(networkId, wifiSsid, BSSID, newSupplicantState);
}
}
@@ -739,13 +742,14 @@ public class WifiMonitor {
* Send the state machine a notification that the state of the supplicant
* has changed.
* @param networkId the configured network on which the state change occurred
- * @param SSID network name
+ * @param wifiSsid network name
* @param BSSID network address
* @param newState the new {@code SupplicantState}
*/
- void notifySupplicantStateChange(int networkId, String SSID, String BSSID, SupplicantState newState) {
+ void notifySupplicantStateChange(int networkId, WifiSsid wifiSsid, String BSSID,
+ SupplicantState newState) {
mStateMachine.sendMessage(mStateMachine.obtainMessage(SUPPLICANT_STATE_CHANGE_EVENT,
- new StateChangeResult(networkId, SSID, BSSID, newState)));
+ new StateChangeResult(networkId, wifiSsid, BSSID, newState)));
}
/**
diff --git a/wifi/java/android/net/wifi/WifiSsid.java b/wifi/java/android/net/wifi/WifiSsid.java
new file mode 100644
index 0000000..6f36111
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiSsid.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+import android.util.Log;
+
+import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+
+/**
+ * Stores SSID octets and handles conversion.
+ *
+ * For Ascii encoded string, any octet < 32 or > 127 is encoded as
+ * a "\x" followed by the hex representation of the octet.
+ * Exception chars are ", \, \e, \n, \r, \t which are escaped by a \
+ * See src/utils/common.c for the implementation in the supplicant.
+ *
+ * @hide
+ */
+public class WifiSsid implements Parcelable {
+ private static final String TAG = "WifiSsid";
+
+ public ByteArrayOutputStream octets = new ByteArrayOutputStream(32);
+
+ private static final int HEX_RADIX = 16;
+ public static final String NONE = "<unknown ssid>";
+
+ private WifiSsid() {
+ }
+
+ public static WifiSsid createFromAsciiEncoded(String asciiEncoded) {
+ WifiSsid a = new WifiSsid();
+ a.convertToBytes(asciiEncoded);
+ return a;
+ }
+
+ public static WifiSsid createFromHex(String hexStr) {
+ WifiSsid a = new WifiSsid();
+ int length = 0;
+ if (hexStr == null) return a;
+
+ if (hexStr.startsWith("0x") || hexStr.startsWith("0X")) {
+ hexStr = hexStr.substring(2);
+ }
+
+ for (int i = 0; i < hexStr.length()-1; i += 2) {
+ int val;
+ try {
+ val = Integer.parseInt(hexStr.substring(i, i + 2), HEX_RADIX);
+ } catch(NumberFormatException e) {
+ val = 0;
+ }
+ a.octets.write(val);
+ }
+ return a;
+ }
+
+ /* This function is equivalent to printf_decode() at src/utils/common.c in
+ * the supplicant */
+ private void convertToBytes(String asciiEncoded) {
+ int i = 0;
+ int val = 0;
+ while (i< asciiEncoded.length()) {
+ char c = asciiEncoded.charAt(i);
+ switch (c) {
+ case '\\':
+ i++;
+ switch(asciiEncoded.charAt(i)) {
+ case '\\':
+ octets.write('\\');
+ break;
+ case '"':
+ octets.write('"');
+ break;
+ case 'n':
+ octets.write('\n');
+ break;
+ case 'r':
+ octets.write('\r');
+ break;
+ case 't':
+ octets.write('\t');
+ break;
+ case 'e':
+ octets.write(27); //escape char
+ break;
+ case 'x':
+ i++;
+ try {
+ val = Integer.parseInt(asciiEncoded.substring(i, i + 2), HEX_RADIX);
+ } catch (NumberFormatException e) {
+ val = -1;
+ }
+ if (val < 0) {
+ val = Character.digit(asciiEncoded.charAt(i), HEX_RADIX);
+ if (val < 0) break;
+ octets.write(val);
+ i++;
+ } else {
+ octets.write(val);
+ i += 2;
+ }
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ val = asciiEncoded.charAt(i) - '0';
+ i++;
+ if (asciiEncoded.charAt(i) >= '0' && asciiEncoded.charAt(i) <= '7') {
+ val = val * 8 + asciiEncoded.charAt(i) - '0';
+ i++;
+ }
+ if (asciiEncoded.charAt(i) >= '0' && asciiEncoded.charAt(i) <= '7') {
+ val = val * 8 + asciiEncoded.charAt(i) - '0';
+ i++;
+ }
+ octets.write(val);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ octets.write(c);
+ i++;
+ break;
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ if (octets.size() <= 0) return "";
+ // TODO: Handle conversion to other charsets upon failure
+ Charset charset = Charset.forName("UTF-8");
+ CharsetDecoder decoder = charset.newDecoder()
+ .onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE);
+ CharBuffer out = CharBuffer.allocate(32);
+
+ CoderResult result = decoder.decode(ByteBuffer.wrap(octets.toByteArray()), out, true);
+ out.flip();
+ if (result.isError()) {
+ return NONE;
+ }
+ return out.toString();
+ }
+
+ /** @hide */
+ public byte[] getOctets() {
+ return octets.toByteArray();
+ }
+
+ /** @hide */
+ public String getHexString() {
+ String out = "0x";
+ byte[] ssidbytes = getOctets();
+ for (int i = 0; i < octets.size(); i++) {
+ out += String.format("%02x", ssidbytes[i]);
+ }
+ return out;
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(octets.size());
+ dest.writeByteArray(octets.toByteArray());
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public static final Creator<WifiSsid> CREATOR =
+ new Creator<WifiSsid>() {
+ public WifiSsid createFromParcel(Parcel in) {
+ WifiSsid ssid = new WifiSsid();
+ int length = in.readInt();
+ byte b[] = new byte[length];
+ in.readByteArray(b);
+ ssid.octets.write(b, 0, length);
+ return ssid;
+ }
+
+ public WifiSsid[] newArray(int size) {
+ return new WifiSsid[size];
+ }
+ };
+}
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 40111fa..2e50b08 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -1403,7 +1403,7 @@ public class WifiStateMachine extends StateMachine {
int freq = 0;
long tsf = 0;
String flags = "";
- String ssid = "";
+ WifiSsid wifiSsid = null;
if (scanResults == null) {
return;
@@ -1441,22 +1441,26 @@ public class WifiStateMachine extends StateMachine {
} else if (line.startsWith(FLAGS_STR)) {
flags = line.substring(FLAGS_STR.length());
} else if (line.startsWith(SSID_STR)) {
- ssid = line.substring(SSID_STR.length());
- if (ssid == null) ssid = "";
+ wifiSsid = WifiSsid.createFromAsciiEncoded(
+ line.substring(SSID_STR.length()));
} else if (line.startsWith(DELIMITER_STR)) {
if (bssid != null) {
+ String ssid = (wifiSsid != null) ? wifiSsid.toString() : WifiSsid.NONE;
String key = bssid + ssid;
ScanResult scanResult = mScanResultCache.get(key);
if (scanResult != null) {
scanResult.level = level;
- scanResult.SSID = ssid;
+ scanResult.wifiSsid = wifiSsid;
+ // Keep existing API
+ scanResult.SSID = (wifiSsid != null) ? wifiSsid.toString() :
+ WifiSsid.NONE;
scanResult.capabilities = flags;
scanResult.frequency = freq;
scanResult.timestamp = tsf;
} else {
scanResult =
new ScanResult(
- ssid, bssid, flags, level, freq, tsf);
+ wifiSsid, bssid, flags, level, freq, tsf);
mScanResultCache.put(key, scanResult);
}
mScanResults.add(scanResult);
@@ -1466,7 +1470,7 @@ public class WifiStateMachine extends StateMachine {
freq = 0;
tsf = 0;
flags = "";
- ssid = "";
+ wifiSsid = null;
}
}
}
@@ -1652,7 +1656,7 @@ public class WifiStateMachine extends StateMachine {
}
mWifiInfo.setBSSID(stateChangeResult.BSSID);
- mWifiInfo.setSSID(stateChangeResult.SSID);
+ mWifiInfo.setSSID(stateChangeResult.wifiSsid);
mSupplicantStateTracker.sendMessage(Message.obtain(message));