diff options
Diffstat (limited to 'wifi/java/android/net')
| -rw-r--r-- | wifi/java/android/net/wifi/ScanResult.java | 35 | ||||
| -rw-r--r-- | wifi/java/android/net/wifi/StateChangeResult.java | 7 | ||||
| -rw-r--r-- | wifi/java/android/net/wifi/WifiConfigStore.java | 8 | ||||
| -rw-r--r-- | wifi/java/android/net/wifi/WifiConfiguration.java | 21 | ||||
| -rw-r--r-- | wifi/java/android/net/wifi/WifiInfo.java | 44 | ||||
| -rw-r--r-- | wifi/java/android/net/wifi/WifiMonitor.java | 16 | ||||
| -rw-r--r-- | wifi/java/android/net/wifi/WifiSsid.java | 217 | ||||
| -rw-r--r-- | wifi/java/android/net/wifi/WifiStateMachine.java | 18 |
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)); |
