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.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.SystemApi; 23 import android.net.wifi.ScanResult; 24 import android.net.wifi.WifiInfo; 25 import android.net.wifi.WifiManager; 26 import android.os.Parcel; 27 import android.os.Parcelable; 28 import android.text.TextUtils; 29 import android.util.Log; 30 31 import java.lang.annotation.Retention; 32 import java.lang.annotation.RetentionPolicy; 33 import java.util.Objects; 34 35 /** 36 * Information which identifies a specific network. 37 * 38 * @hide 39 */ 40 @SystemApi 41 // NOTE: Ideally, we would abstract away the details of what identifies a network of a specific 42 // type, so that all networks appear the same and can be scored without concern to the network type 43 // itself. However, because no such cross-type identifier currently exists in the Android framework, 44 // and because systems might obtain information about networks from sources other than Android 45 // devices, we need to provide identifying details about each specific network type (wifi, cell, 46 // etc.) so that clients can pull out these details depending on the type of network. 47 public class NetworkKey implements Parcelable { 48 49 private static final String TAG = "NetworkKey"; 50 51 /** A wifi network, for which {@link #wifiKey} will be populated. */ 52 public static final int TYPE_WIFI = 1; 53 54 /** @hide */ 55 @Retention(RetentionPolicy.SOURCE) 56 @IntDef(prefix = {"TYPE_"}, value = { 57 TYPE_WIFI 58 }) 59 public @interface NetworkType {} 60 61 /** 62 * The type of this network. 63 * @see #TYPE_WIFI 64 */ 65 public final int type; 66 67 /** 68 * Information identifying a Wi-Fi network. Only set when {@link #type} equals 69 * {@link #TYPE_WIFI}. 70 */ 71 public final WifiKey wifiKey; 72 73 /** 74 * Constructs a new NetworkKey for the given wifi {@link ScanResult}. 75 * 76 * @return A new {@link NetworkKey} instance or <code>null</code> if the given 77 * {@link ScanResult} instance is malformed. 78 * @throws NullPointerException 79 */ 80 @Nullable createFromScanResult(@onNull ScanResult result)81 public static NetworkKey createFromScanResult(@NonNull ScanResult result) { 82 Objects.requireNonNull(result); 83 final String ssid = result.SSID; 84 if (TextUtils.isEmpty(ssid) || ssid.equals(WifiManager.UNKNOWN_SSID)) { 85 return null; 86 } 87 final String bssid = result.BSSID; 88 if (TextUtils.isEmpty(bssid)) { 89 return null; 90 } 91 92 try { 93 WifiKey wifiKey = new WifiKey(String.format("\"%s\"", ssid), bssid); 94 return new NetworkKey(wifiKey); 95 } catch (IllegalArgumentException e) { 96 Log.e(TAG, "Unable to create WifiKey.", e); 97 return null; 98 } 99 } 100 101 /** 102 * Constructs a new NetworkKey for the given {@link WifiInfo}. 103 * 104 * @param wifiInfo the {@link WifiInfo} to create a {@link NetworkKey} for. 105 * @return A new {@link NetworkKey} instance or <code>null</code> if the given {@link WifiInfo} 106 * instance doesn't represent a connected WiFi network. 107 * @hide 108 */ 109 @Nullable createFromWifiInfo(@ullable WifiInfo wifiInfo)110 public static NetworkKey createFromWifiInfo(@Nullable WifiInfo wifiInfo) { 111 if (wifiInfo != null) { 112 final String ssid = wifiInfo.getSSID(); 113 final String bssid = wifiInfo.getBSSID(); 114 if (!TextUtils.isEmpty(ssid) && !ssid.equals(WifiManager.UNKNOWN_SSID) 115 && !TextUtils.isEmpty(bssid)) { 116 WifiKey wifiKey; 117 try { 118 wifiKey = new WifiKey(ssid, bssid); 119 } catch (IllegalArgumentException e) { 120 Log.e(TAG, "Unable to create WifiKey.", e); 121 return null; 122 } 123 return new NetworkKey(wifiKey); 124 } 125 } 126 return null; 127 } 128 129 /** 130 * Construct a new {@link NetworkKey} for a Wi-Fi network. 131 * @param wifiKey the {@link WifiKey} identifying this Wi-Fi network. 132 */ NetworkKey(WifiKey wifiKey)133 public NetworkKey(WifiKey wifiKey) { 134 this.type = TYPE_WIFI; 135 this.wifiKey = wifiKey; 136 } 137 NetworkKey(Parcel in)138 private NetworkKey(Parcel in) { 139 type = in.readInt(); 140 switch (type) { 141 case TYPE_WIFI: 142 wifiKey = WifiKey.CREATOR.createFromParcel(in); 143 break; 144 default: 145 throw new IllegalArgumentException("Parcel has unknown type: " + type); 146 } 147 } 148 149 @Override describeContents()150 public int describeContents() { 151 return 0; 152 } 153 154 @Override writeToParcel(Parcel out, int flags)155 public void writeToParcel(Parcel out, int flags) { 156 out.writeInt(type); 157 switch (type) { 158 case TYPE_WIFI: 159 wifiKey.writeToParcel(out, flags); 160 break; 161 default: 162 throw new IllegalStateException("NetworkKey has unknown type " + type); 163 } 164 } 165 166 @Override equals(@ullable Object o)167 public boolean equals(@Nullable Object o) { 168 if (this == o) return true; 169 if (o == null || getClass() != o.getClass()) return false; 170 171 NetworkKey that = (NetworkKey) o; 172 173 return type == that.type && Objects.equals(wifiKey, that.wifiKey); 174 } 175 176 @Override hashCode()177 public int hashCode() { 178 return Objects.hash(type, wifiKey); 179 } 180 181 @NonNull 182 @Override toString()183 public String toString() { 184 switch (type) { 185 case TYPE_WIFI: 186 return wifiKey.toString(); 187 default: 188 // Don't throw an exception here in case someone is logging this object in a catch 189 // block for debugging purposes. 190 return "InvalidKey"; 191 } 192 } 193 194 public static final @android.annotation.NonNull Parcelable.Creator<NetworkKey> CREATOR = 195 new Parcelable.Creator<NetworkKey>() { 196 @Override 197 public NetworkKey createFromParcel(Parcel in) { 198 return new NetworkKey(in); 199 } 200 201 @Override 202 public NetworkKey[] newArray(int size) { 203 return new NetworkKey[size]; 204 } 205 }; 206 } 207