1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package android.net; 18 19 import android.annotation.Nullable; 20 import android.annotation.SystemApi; 21 import android.net.wifi.ScanResult; 22 import android.net.wifi.WifiInfo; 23 import android.net.wifi.WifiSsid; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 import android.text.TextUtils; 27 import android.util.Log; 28 29 import java.util.Objects; 30 31 /** 32 * Information which identifies a specific network. 33 * 34 * @hide 35 */ 36 @SystemApi 37 // NOTE: Ideally, we would abstract away the details of what identifies a network of a specific 38 // type, so that all networks appear the same and can be scored without concern to the network type 39 // itself. However, because no such cross-type identifier currently exists in the Android framework, 40 // and because systems might obtain information about networks from sources other than Android 41 // devices, we need to provide identifying details about each specific network type (wifi, cell, 42 // etc.) so that clients can pull out these details depending on the type of network. 43 public class NetworkKey implements Parcelable { 44 45 private static final String TAG = "NetworkKey"; 46 47 /** A wifi network, for which {@link #wifiKey} will be populated. */ 48 public static final int TYPE_WIFI = 1; 49 50 /** 51 * The type of this network. 52 * @see #TYPE_WIFI 53 */ 54 public final int type; 55 56 /** 57 * Information identifying a Wi-Fi network. Only set when {@link #type} equals 58 * {@link #TYPE_WIFI}. 59 */ 60 public final WifiKey wifiKey; 61 62 /** 63 * Constructs a new NetworkKey for the given wifi {@link ScanResult}. 64 * 65 * @return A new {@link NetworkKey} instance or <code>null</code> if the given 66 * {@link ScanResult} instance is malformed. 67 * @hide 68 */ 69 @Nullable createFromScanResult(@ullable ScanResult result)70 public static NetworkKey createFromScanResult(@Nullable ScanResult result) { 71 if (result != null && result.wifiSsid != null) { 72 final String ssid = result.wifiSsid.toString(); 73 final String bssid = result.BSSID; 74 if (!TextUtils.isEmpty(ssid) && !ssid.equals(WifiSsid.NONE) 75 && !TextUtils.isEmpty(bssid)) { 76 WifiKey wifiKey; 77 try { 78 wifiKey = new WifiKey(String.format("\"%s\"", ssid), bssid); 79 } catch (IllegalArgumentException e) { 80 Log.e(TAG, "Unable to create WifiKey.", e); 81 return null; 82 } 83 return new NetworkKey(wifiKey); 84 } 85 } 86 return null; 87 } 88 89 /** 90 * Constructs a new NetworkKey for the given {@link WifiInfo}. 91 * 92 * @param wifiInfo the {@link WifiInfo} to create a {@link NetworkKey} for. 93 * @return A new {@link NetworkKey} instance or <code>null</code> if the given {@link WifiInfo} 94 * instance doesn't represent a connected WiFi network. 95 * @hide 96 */ 97 @Nullable createFromWifiInfo(@ullable WifiInfo wifiInfo)98 public static NetworkKey createFromWifiInfo(@Nullable WifiInfo wifiInfo) { 99 if (wifiInfo != null) { 100 final String ssid = wifiInfo.getSSID(); 101 final String bssid = wifiInfo.getBSSID(); 102 if (!TextUtils.isEmpty(ssid) && !ssid.equals(WifiSsid.NONE) 103 && !TextUtils.isEmpty(bssid)) { 104 WifiKey wifiKey; 105 try { 106 wifiKey = new WifiKey(ssid, bssid); 107 } catch (IllegalArgumentException e) { 108 Log.e(TAG, "Unable to create WifiKey.", e); 109 return null; 110 } 111 return new NetworkKey(wifiKey); 112 } 113 } 114 return null; 115 } 116 117 /** 118 * Construct a new {@link NetworkKey} for a Wi-Fi network. 119 * @param wifiKey the {@link WifiKey} identifying this Wi-Fi network. 120 */ NetworkKey(WifiKey wifiKey)121 public NetworkKey(WifiKey wifiKey) { 122 this.type = TYPE_WIFI; 123 this.wifiKey = wifiKey; 124 } 125 NetworkKey(Parcel in)126 private NetworkKey(Parcel in) { 127 type = in.readInt(); 128 switch (type) { 129 case TYPE_WIFI: 130 wifiKey = WifiKey.CREATOR.createFromParcel(in); 131 break; 132 default: 133 throw new IllegalArgumentException("Parcel has unknown type: " + type); 134 } 135 } 136 137 @Override describeContents()138 public int describeContents() { 139 return 0; 140 } 141 142 @Override writeToParcel(Parcel out, int flags)143 public void writeToParcel(Parcel out, int flags) { 144 out.writeInt(type); 145 switch (type) { 146 case TYPE_WIFI: 147 wifiKey.writeToParcel(out, flags); 148 break; 149 default: 150 throw new IllegalStateException("NetworkKey has unknown type " + type); 151 } 152 } 153 154 @Override equals(Object o)155 public boolean equals(Object o) { 156 if (this == o) return true; 157 if (o == null || getClass() != o.getClass()) return false; 158 159 NetworkKey that = (NetworkKey) o; 160 161 return type == that.type && Objects.equals(wifiKey, that.wifiKey); 162 } 163 164 @Override hashCode()165 public int hashCode() { 166 return Objects.hash(type, wifiKey); 167 } 168 169 @Override toString()170 public String toString() { 171 switch (type) { 172 case TYPE_WIFI: 173 return wifiKey.toString(); 174 default: 175 // Don't throw an exception here in case someone is logging this object in a catch 176 // block for debugging purposes. 177 return "InvalidKey"; 178 } 179 } 180 181 public static final @android.annotation.NonNull Parcelable.Creator<NetworkKey> CREATOR = 182 new Parcelable.Creator<NetworkKey>() { 183 @Override 184 public NetworkKey createFromParcel(Parcel in) { 185 return new NetworkKey(in); 186 } 187 188 @Override 189 public NetworkKey[] newArray(int size) { 190 return new NetworkKey[size]; 191 } 192 }; 193 } 194