1 /* 2 * Copyright (C) 2012 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.wifi.p2p.nsd; 18 19 import android.annotation.FlaggedApi; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.RequiresApi; 23 import android.compat.annotation.UnsupportedAppUsage; 24 import android.net.wifi.util.Environment; 25 import android.os.Build; 26 import android.os.Parcel; 27 import android.os.Parcelable; 28 29 import com.android.wifi.flags.Flags; 30 31 import java.util.ArrayList; 32 import java.util.List; 33 import java.util.Objects; 34 35 /** 36 * A class for storing service information that is advertised 37 * over a Wi-Fi peer-to-peer setup 38 * 39 * @see WifiP2pUpnpServiceInfo 40 * @see WifiP2pDnsSdServiceInfo 41 */ 42 public class WifiP2pServiceInfo implements Parcelable { 43 44 /** 45 * All service protocol types. 46 */ 47 public static final int SERVICE_TYPE_ALL = 0; 48 49 /** 50 * DNS based service discovery protocol. 51 */ 52 public static final int SERVICE_TYPE_BONJOUR = 1; 53 54 /** 55 * UPnP protocol. 56 */ 57 public static final int SERVICE_TYPE_UPNP = 2; 58 59 /** 60 * WS-Discovery protocol 61 * @hide 62 */ 63 public static final int SERVICE_TYPE_WS_DISCOVERY = 3; 64 65 /** 66 * Vendor Specific protocol 67 */ 68 public static final int SERVICE_TYPE_VENDOR_SPECIFIC = 255; 69 70 /** 71 * the list of query string for wpa_supplicant 72 * 73 * e.g) 74 * # IP Printing over TCP (PTR) (RDATA=MyPrinter._ipp._tcp.local.) 75 * {"bonjour", "045f697070c00c000c01", "094d795072696e746572c027" 76 * 77 * # IP Printing over TCP (TXT) (RDATA=txtvers=1,pdl=application/postscript) 78 * {"bonjour", "096d797072696e746572045f697070c00c001001", 79 * "09747874766572733d311a70646c3d6170706c69636174696f6e2f706f7374736372797074"} 80 * 81 * [UPnP] 82 * # UPnP uuid 83 * {"upnp", "10", "uuid:6859dede-8574-59ab-9332-123456789012"} 84 * 85 * # UPnP rootdevice 86 * {"upnp", "10", "uuid:6859dede-8574-59ab-9332-123456789012::upnp:rootdevice"} 87 * 88 * # UPnP device 89 * {"upnp", "10", "uuid:6859dede-8574-59ab-9332-123456789012::urn:schemas-upnp 90 * -org:device:InternetGatewayDevice:1"} 91 * 92 * # UPnP service 93 * {"upnp", "10", "uuid:6859dede-8574-59ab-9322-123456789012::urn:schemas-upnp 94 * -org:service:ContentDirectory:2"} 95 */ 96 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 97 private List<String> mQueryList; 98 99 /** 100 * This field is used only when the service advertisement is using un-synchronized service 101 * discovery (USD) protocol. Refer Wi-Fi Alliance Wi-Fi Direct R2 specification section 3.7 - 102 * "Unsynchronized Service Discovery (USD)" for the details. 103 */ 104 private WifiP2pUsdBasedServiceConfig mUsdServiceConfig; 105 106 /** 107 * Service advertisement session ID / Publish ID for USD based service advertisement. 108 * This is a nonzero value used to identify the instance of service advertisement. 109 * This value is filled in the service discovery response frame (USD publish frame), 110 * Service descriptor attribute (SDA) - instance ID field. 111 */ 112 /** 113 * Service advertisement session ID (Advertiser ID) for USD based service discovery response. 114 * The session ID is used to identify a local advertisement session. 115 * It is a nonzero ID in the range of 1 to 255 filled in the Service descriptor attribute (SDA) 116 * - instance ID field of the service discovery response frame (Publish frame). 117 * Zero by default indicates that the USD session for this service is not running. 118 */ 119 private int mUsdSessionId; 120 121 /** 122 * This is only used in subclass. 123 * 124 * @param queryList query string for wpa_supplicant 125 * @hide 126 */ 127 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) WifiP2pServiceInfo(List<String> queryList)128 protected WifiP2pServiceInfo(List<String> queryList) { 129 if (queryList == null) { 130 throw new IllegalArgumentException("query list cannot be null"); 131 } 132 mQueryList = queryList; 133 } 134 135 /** 136 * This constructor is only used in Parcelable. 137 * 138 * @param queryList query string for wpa_supplicant 139 * @param usdConfig See {@link WifiP2pUsdBasedServiceConfig} 140 * @param usdSessionId The USD based service advertisement session ID. 141 */ WifiP2pServiceInfo(List<String> queryList, @NonNull WifiP2pUsdBasedServiceConfig usdConfig, int usdSessionId)142 private WifiP2pServiceInfo(List<String> queryList, 143 @NonNull WifiP2pUsdBasedServiceConfig usdConfig, int usdSessionId) { 144 mQueryList = queryList; 145 mUsdServiceConfig = usdConfig; 146 mUsdSessionId = usdSessionId; 147 } 148 149 /** 150 * Constructor for creating a service information for advertising the service using 151 * un-synchronized service discovery (USD) protocol. Refer Wi-Fi Alliance Wi-Fi Direct R2 152 * specification section 3.7 - "Unsynchronized Service Discovery (USD)" for the details. 153 * 154 * @param usdConfig See {@link WifiP2pUsdBasedServiceConfig} 155 * 156 * @return service info containing USD based service configuration. 157 */ 158 @RequiresApi(Build.VERSION_CODES.BAKLAVA) 159 @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2) WifiP2pServiceInfo(@onNull WifiP2pUsdBasedServiceConfig usdConfig)160 public WifiP2pServiceInfo(@NonNull WifiP2pUsdBasedServiceConfig usdConfig) { 161 if (!Environment.isSdkAtLeastB()) { 162 throw new UnsupportedOperationException(); 163 } 164 Objects.requireNonNull(usdConfig, "usd based service config cannot be null"); 165 mUsdServiceConfig = usdConfig; 166 } 167 168 /** 169 * Return the list of the query string for wpa_supplicant. 170 * 171 * @return the list of the query string for wpa_supplicant. 172 * @hide 173 */ getSupplicantQueryList()174 public List<String> getSupplicantQueryList() { 175 return mQueryList; 176 } 177 178 /** 179 * Get the service information configured to advertise using un-synchronized service discovery 180 * (USD) protocol. 181 * See {@link #WifiP2pServiceInfo(WifiP2pUsdBasedServiceConfig)} 182 * 183 * @return A valid or not null {@link WifiP2pUsdBasedServiceConfig} if the service information 184 * is configured to advertise using un-synchronized service discovery (USD) protocol. 185 * Otherwise, it is null. 186 */ 187 @RequiresApi(Build.VERSION_CODES.BAKLAVA) 188 @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2) 189 @Nullable getWifiP2pUsdBasedServiceConfig()190 public WifiP2pUsdBasedServiceConfig getWifiP2pUsdBasedServiceConfig() { 191 if (!Environment.isSdkAtLeastB()) { 192 throw new UnsupportedOperationException(); 193 } 194 return mUsdServiceConfig; 195 } 196 197 /** 198 * Return the Service advertisement session ID for USD based service advertisement. 199 * 200 * @return session id 201 * @hide 202 */ 203 /** 204 * Return the Service advertisement session ID for USD based service advertisement. 205 * This ID is used to identify a service advertisement session. 206 * 207 * @return A nonzero ID in the range of 1 to 255 when the session is running. 208 * @hide 209 */ getUsdSessionId()210 public int getUsdSessionId() { 211 return mUsdSessionId; 212 } 213 214 /** 215 * Set the service advertisement session ID for USD based service advertisement. 216 * Default value is zero. 217 * 218 * @param sessionId nonzero session ID is set when the USD session for this service is started. 219 * @hide 220 */ setUsdSessionId(int sessionId)221 public void setUsdSessionId(int sessionId) { 222 mUsdSessionId = sessionId; 223 } 224 225 /** 226 * Converts byte array to hex string. 227 * 228 * @param data 229 * @return hex string. 230 * @hide 231 */ bin2HexStr(byte[] data)232 static String bin2HexStr(byte[] data) { 233 StringBuffer sb = new StringBuffer(); 234 235 for (byte b: data) { 236 String s = null; 237 try { 238 s = Integer.toHexString(b & 0xff); 239 } catch (Exception e) { 240 e.printStackTrace(); 241 return null; 242 } 243 //add 0 padding 244 if (s.length() == 1) { 245 sb.append('0'); 246 } 247 sb.append(s); 248 } 249 return sb.toString(); 250 } 251 252 @Override equals(Object o)253 public boolean equals(Object o) { 254 if (o == this) { 255 return true; 256 } 257 if (!(o instanceof WifiP2pServiceInfo)) { 258 return false; 259 } 260 261 /* 262 * Don't compare USD based service advertisement session ID. 263 * The session ID may be changed on each service discovery advertisement. 264 */ 265 WifiP2pServiceInfo servInfo = (WifiP2pServiceInfo) o; 266 return Objects.equals(mQueryList, servInfo.mQueryList) 267 && Objects.equals(mUsdServiceConfig, servInfo.mUsdServiceConfig); 268 } 269 270 @Override hashCode()271 public int hashCode() { 272 int result = 17; 273 result = 31 * result + (mQueryList == null ? 0 : mQueryList.hashCode()); 274 result = 31 * result + (mUsdServiceConfig == null ? 0 : mUsdServiceConfig.hashCode()); 275 return result; 276 } 277 278 /** Implement the Parcelable interface {@hide} */ describeContents()279 public int describeContents() { 280 return 0; 281 } 282 283 /** Implement the Parcelable interface {@hide} */ writeToParcel(Parcel dest, int flags)284 public void writeToParcel(Parcel dest, int flags) { 285 dest.writeStringList(mQueryList); 286 if (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()) { 287 dest.writeParcelable(mUsdServiceConfig, flags); 288 dest.writeInt(mUsdSessionId); 289 } 290 } 291 292 /** Implement the Parcelable interface {@hide} */ 293 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 294 public static final @android.annotation.NonNull Creator<WifiP2pServiceInfo> CREATOR = 295 new Creator<WifiP2pServiceInfo>() { 296 public WifiP2pServiceInfo createFromParcel(Parcel in) { 297 List<String> data = new ArrayList<String>(); 298 in.readStringList(data); 299 WifiP2pUsdBasedServiceConfig config = null; 300 int usdSessionId = 0; 301 if (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()) { 302 config = in.readParcelable( 303 WifiP2pUsdBasedServiceConfig.class.getClassLoader()); 304 usdSessionId = in.readInt(); 305 } 306 return new WifiP2pServiceInfo(data, config, usdSessionId); 307 } 308 public WifiP2pServiceInfo[] newArray(int size) { 309 return new WifiP2pServiceInfo[size]; 310 } 311 }; 312 } 313