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 */ 79 @Nullable createFromScanResult(@ullable ScanResult result)80 public static NetworkKey createFromScanResult(@Nullable ScanResult result) { 81 if (result == null) { 82 return null; 83 } 84 final String ssid = result.SSID; 85 if (TextUtils.isEmpty(ssid) || ssid.equals(WifiManager.UNKNOWN_SSID)) { 86 return null; 87 } 88 final String bssid = result.BSSID; 89 if (TextUtils.isEmpty(bssid)) { 90 return null; 91 } 92 93 try { 94 final WifiKey wifiKey = new WifiKey(String.format("\"%s\"", ssid), bssid); 95 return new NetworkKey(wifiKey); 96 } catch (IllegalArgumentException e) { 97 Log.e(TAG, "Unable to create WifiKey.", e); 98 return null; 99 } 100 } 101 102 /** 103 * Constructs a new NetworkKey for the given {@link WifiInfo}. 104 * 105 * @param wifiInfo the {@link WifiInfo} to create a {@link NetworkKey} for. 106 * @return A new {@link NetworkKey} instance or <code>null</code> if the given {@link WifiInfo} 107 * instance doesn't represent a connected WiFi network. 108 * @hide 109 */ 110 @Nullable createFromWifiInfo(@ullable WifiInfo wifiInfo)111 public static NetworkKey createFromWifiInfo(@Nullable WifiInfo wifiInfo) { 112 if (wifiInfo != null) { 113 final String ssid = wifiInfo.getSSID(); 114 final String bssid = wifiInfo.getBSSID(); 115 if (!TextUtils.isEmpty(ssid) && !ssid.equals(WifiManager.UNKNOWN_SSID) 116 && !TextUtils.isEmpty(bssid)) { 117 WifiKey wifiKey; 118 try { 119 wifiKey = new WifiKey(ssid, bssid); 120 } catch (IllegalArgumentException e) { 121 Log.e(TAG, "Unable to create WifiKey.", e); 122 return null; 123 } 124 return new NetworkKey(wifiKey); 125 } 126 } 127 return null; 128 } 129 130 /** 131 * Construct a new {@link NetworkKey} for a Wi-Fi network. 132 * @param wifiKey the {@link WifiKey} identifying this Wi-Fi network. 133 */ NetworkKey(WifiKey wifiKey)134 public NetworkKey(WifiKey wifiKey) { 135 this.type = TYPE_WIFI; 136 this.wifiKey = wifiKey; 137 } 138 NetworkKey(Parcel in)139 private NetworkKey(Parcel in) { 140 type = in.readInt(); 141 switch (type) { 142 case TYPE_WIFI: 143 wifiKey = WifiKey.CREATOR.createFromParcel(in); 144 break; 145 default: 146 throw new IllegalArgumentException("Parcel has unknown type: " + type); 147 } 148 } 149 150 @Override describeContents()151 public int describeContents() { 152 return 0; 153 } 154 155 @Override writeToParcel(Parcel out, int flags)156 public void writeToParcel(Parcel out, int flags) { 157 out.writeInt(type); 158 switch (type) { 159 case TYPE_WIFI: 160 wifiKey.writeToParcel(out, flags); 161 break; 162 default: 163 throw new IllegalStateException("NetworkKey has unknown type " + type); 164 } 165 } 166 167 @Override equals(@ullable Object o)168 public boolean equals(@Nullable Object o) { 169 if (this == o) return true; 170 if (o == null || getClass() != o.getClass()) return false; 171 172 NetworkKey that = (NetworkKey) o; 173 174 return type == that.type && Objects.equals(wifiKey, that.wifiKey); 175 } 176 177 @Override hashCode()178 public int hashCode() { 179 return Objects.hash(type, wifiKey); 180 } 181 182 @NonNull 183 @Override toString()184 public String toString() { 185 switch (type) { 186 case TYPE_WIFI: 187 return wifiKey.toString(); 188 default: 189 // Don't throw an exception here in case someone is logging this object in a catch 190 // block for debugging purposes. 191 return "InvalidKey"; 192 } 193 } 194 195 public static final @android.annotation.NonNull Parcelable.Creator<NetworkKey> CREATOR = 196 new Parcelable.Creator<NetworkKey>() { 197 @Override 198 public NetworkKey createFromParcel(Parcel in) { 199 return new NetworkKey(in); 200 } 201 202 @Override 203 public NetworkKey[] newArray(int size) { 204 return new NetworkKey[size]; 205 } 206 }; 207 } 208