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; 18 19 import android.annotation.IntDef; 20 import android.annotation.IntRange; 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.compat.annotation.UnsupportedAppUsage; 24 import android.os.Build; 25 import android.os.Parcel; 26 import android.os.Parcelable; 27 28 import androidx.annotation.RequiresApi; 29 30 import com.android.modules.utils.build.SdkLevel; 31 32 import java.lang.annotation.Retention; 33 import java.lang.annotation.RetentionPolicy; 34 import java.util.Locale; 35 36 /** 37 * A class representing Wifi Display information for a device. 38 * 39 * See Wifi Display technical specification v1.0.0, section 5.1.2. 40 * See Wifi Display technical specification v2.0.0, section 5.1.12 for Wifi Display R2. 41 */ 42 public final class WifiP2pWfdInfo implements Parcelable { 43 44 private boolean mEnabled; 45 46 /** Device information bitmap */ 47 private int mDeviceInfo; 48 49 /** R2 Device information bitmap */ 50 private int mR2DeviceInfo = -1; 51 52 /** @hide */ 53 @Retention(RetentionPolicy.SOURCE) 54 @IntDef(prefix = { "DEVICE_TYPE_" }, value = { 55 DEVICE_TYPE_WFD_SOURCE, 56 DEVICE_TYPE_PRIMARY_SINK, 57 DEVICE_TYPE_SECONDARY_SINK, 58 DEVICE_TYPE_SOURCE_OR_PRIMARY_SINK}) 59 public @interface DeviceType {} 60 61 /** The device is a Wifi Display Source. */ 62 public static final int DEVICE_TYPE_WFD_SOURCE = 0; 63 /** The device is a primary sink. */ 64 public static final int DEVICE_TYPE_PRIMARY_SINK = 1; 65 /** The device is a secondary sink. This type is only supported by R1. */ 66 public static final int DEVICE_TYPE_SECONDARY_SINK = 2; 67 /** The device is dual-role capable i.e. either a WFD source or a primary sink. */ 68 public static final int DEVICE_TYPE_SOURCE_OR_PRIMARY_SINK = 3; 69 70 /** @hide */ 71 @Retention(RetentionPolicy.SOURCE) 72 @IntDef(prefix = { "PREFERRED_CONNECTIVITY_" }, value = { 73 PREFERRED_CONNECTIVITY_P2P, 74 PREFERRED_CONNECTIVITY_TDLS}) 75 public @interface PreferredConnectivity {} 76 77 /** Wifi Display (WFD) preferred connectivity is Wifi Direct (P2P). */ 78 public static final int PREFERRED_CONNECTIVITY_P2P = 0; 79 /** Wifi Display (WFD) preferred connectivity is TDLS. */ 80 public static final int PREFERRED_CONNECTIVITY_TDLS = 1; 81 82 /** @hide */ 83 @Retention(RetentionPolicy.SOURCE) 84 @IntDef(flag = true, prefix = {"DEVICE_INFO_"}, value = { 85 DEVICE_INFO_DEVICE_TYPE_MASK, 86 DEVICE_INFO_COUPLED_SINK_SUPPORT_AT_SOURCE, 87 DEVICE_INFO_COUPLED_SINK_SUPPORT_AT_SINK, 88 DEVICE_INFO_SESSION_AVAILABLE_MASK, 89 DEVICE_INFO_WFD_SERVICE_DISCOVERY_SUPPORT, 90 DEVICE_INFO_PREFERRED_CONNECTIVITY_MASK, 91 DEVICE_INFO_CONTENT_PROTECTION_SUPPORT, 92 DEVICE_INFO_TIME_SYNCHRONIZATION_SUPPORT, 93 DEVICE_INFO_AUDIO_UNSUPPORTED_AT_PRIMARY_SINK, 94 DEVICE_INFO_AUDIO_ONLY_SUPPORT_AT_SOURCE, 95 DEVICE_INFO_TDLS_PERSISTENT_GROUP, 96 DEVICE_INFO_TDLS_PERSISTENT_GROUP_REINVOKE}) 97 public @interface DeviceInfoMask {} 98 99 /** @hide */ 100 @Retention(RetentionPolicy.SOURCE) 101 @IntDef(flag = true, prefix = {"DEVICE_INFO_"}, value = {DEVICE_INFO_DEVICE_TYPE_MASK}) 102 public @interface R2DeviceInfoMask {} 103 104 /** 105 * {@link #getDeviceInfo()} & {@link #DEVICE_INFO_DEVICE_TYPE_MASK} is one of 106 * {@link #DEVICE_TYPE_WFD_SOURCE}, {@link #DEVICE_TYPE_PRIMARY_SINK}, 107 * {@link #DEVICE_TYPE_SECONDARY_SINK} or {@link #DEVICE_TYPE_SOURCE_OR_PRIMARY_SINK}. 108 * 109 * The bit definition is listed in 5.1.2 WFD Device Information Subelement and 110 * 5.1.12 WFD R2 Device Information Subelement in Wifi Display Technical Specification. 111 */ 112 public static final int DEVICE_INFO_DEVICE_TYPE_MASK = 1 << 1 | 1 << 0; 113 /** 114 * Bit field for {@link #getDeviceInfo()}, indicates that coupled sink is supported at source. 115 * 116 * The bit definition is listed in 5.1.2 WFD Device Information Subelement in 117 * Wifi Display Technical Specification. 118 */ 119 public static final int DEVICE_INFO_COUPLED_SINK_SUPPORT_AT_SOURCE = 1 << 2; 120 /** 121 * Bit field for {@link #getDeviceInfo()}, indicates that coupled sink is supporeted at sink. 122 * 123 * The bit definition is listed in 5.1.2 WFD Device Information Subelement in 124 * Wifi Display Technical Specification. 125 */ 126 public static final int DEVICE_INFO_COUPLED_SINK_SUPPORT_AT_SINK = 1 << 3; 127 private static final int SESSION_AVAILABLE_BIT1 = 1 << 4; 128 private static final int SESSION_AVAILABLE_BIT2 = 1 << 5; 129 /** 130 * Bit field for {@link #getDeviceInfo()}, indicates that Wifi Display session is available. 131 * 132 * The bit definition is listed in 5.1.2 WFD Device Information Subelement in 133 * Wifi Display Technical Specification. 134 */ 135 public static final int DEVICE_INFO_SESSION_AVAILABLE_MASK = 136 SESSION_AVAILABLE_BIT2 | SESSION_AVAILABLE_BIT1; 137 /** 138 * Bit field for {@link #getDeviceInfo()}, indicates that Wifi Display discovery is supported. 139 * 140 * The bit definition is listed in 5.1.2 WFD Device Information Subelement in 141 * Wifi Display Technical Specification. 142 */ 143 public static final int DEVICE_INFO_WFD_SERVICE_DISCOVERY_SUPPORT = 1 << 6; 144 /** 145 * Bit field for {@link #getDeviceInfo()}, indicate the preferred connectifity for Wifi Display. 146 * 147 * The bit definition is listed in 5.1.2 WFD Device Information Subelement in 148 * Wifi Display Technical Specification. 149 * The value is one of {@link #PREFERRED_CONNECTIVITY_P2P} or 150 * {@link #PREFERRED_CONNECTIVITY_TDLS}. 151 */ 152 public static final int DEVICE_INFO_PREFERRED_CONNECTIVITY_MASK = 1 << 7; 153 /** 154 * Bit field for {@link #getDeviceInfo()}, indicate the support of Content Protection 155 * using the HDCP system 2.0/2.1. 156 * 157 * The bit definition is listed in 5.1.2 WFD Device Information Subelement in 158 * Wifi Display Technical Specification. 159 */ 160 public static final int DEVICE_INFO_CONTENT_PROTECTION_SUPPORT = 1 << 8; 161 /** 162 * Bit field for {@link #getDeviceInfo()}, indicate time synchronization 163 * using 802.1AS is supported. 164 * 165 * The bit definition is listed in 5.1.2 WFD Device Information Subelement in 166 * Wifi Display Technical Specification. 167 */ 168 public static final int DEVICE_INFO_TIME_SYNCHRONIZATION_SUPPORT = 1 << 9; 169 /** 170 * Bit field for {@link #getDeviceInfo()}, indicate audio is not supported at primary sink. 171 * 172 * The bit definition is listed in 5.1.2 WFD Device Information Subelement in 173 * Wifi Display Technical Specification. 174 */ 175 public static final int DEVICE_INFO_AUDIO_UNSUPPORTED_AT_PRIMARY_SINK = 1 << 10; 176 /** 177 * Bit field for {@link #getDeviceInfo()}, indicate audo is only supported at source. 178 * 179 * The bit definition is listed in 5.1.2 WFD Device Information Subelement in 180 * Wifi Display Technical Specification. 181 */ 182 public static final int DEVICE_INFO_AUDIO_ONLY_SUPPORT_AT_SOURCE = 1 << 11; 183 /** Bit field for {@link #getDeviceInfo()}, indicate that TDLS persistent group is intended. 184 * 185 * The bit definition is listed in 5.1.2 WFD Device Information Subelement in 186 * Wifi Display Technical Specification. 187 */ 188 public static final int DEVICE_INFO_TDLS_PERSISTENT_GROUP = 1 << 12; 189 /** Bit field for {@link #getDeviceInfo()}, indicate that the request is for 190 * re-invocation of TDLS persistent group. 191 * 192 * The bit definition is listed in 5.1.2 WFD Device Information Subelement in 193 * Wifi Display Technical Specification. 194 */ 195 public static final int DEVICE_INFO_TDLS_PERSISTENT_GROUP_REINVOKE = 1 << 13; 196 197 private int mCtrlPort; 198 199 private int mMaxThroughput; 200 201 /** Default constructor. */ WifiP2pWfdInfo()202 public WifiP2pWfdInfo() {} 203 204 /** @hide */ 205 @UnsupportedAppUsage WifiP2pWfdInfo(int devInfo, int ctrlPort, int maxTput)206 public WifiP2pWfdInfo(int devInfo, int ctrlPort, int maxTput) { 207 mEnabled = true; 208 mDeviceInfo = devInfo; 209 mCtrlPort = ctrlPort; 210 mMaxThroughput = maxTput; 211 mR2DeviceInfo = -1; 212 } 213 214 /** 215 * Return R1 raw device info, See 216 * Wifi Display technical specification v1.0.0, section 5.1.2. 217 * Access bit fields by DEVICE_INFO_* constants. 218 */ 219 @DeviceInfoMask getDeviceInfo()220 public int getDeviceInfo() { 221 return mDeviceInfo; 222 } 223 224 /** 225 * Set Wifi Display R2 raw device info, see 226 * Wifi Display technical specification v2.0.0, section 5.1.12. 227 * Access bit fields by {@link #DEVICE_INFO_DEVICE_TYPE_MASK}. 228 * 229 * @param r2DeviceInfo the raw data of R2 device info. 230 * @hide 231 */ setR2DeviceInfo(int r2DeviceInfo)232 public void setR2DeviceInfo(int r2DeviceInfo) { 233 mR2DeviceInfo = r2DeviceInfo; 234 } 235 236 /** 237 * Return R2 raw device info, See 238 * Wifi Display technical specification v2.0.0, section 5.1.12. 239 * Access bit fields by {@link #DEVICE_INFO_DEVICE_TYPE_MASK}. 240 */ 241 @R2DeviceInfoMask getR2DeviceInfo()242 public int getR2DeviceInfo() { 243 return mR2DeviceInfo; 244 } 245 246 /** Returns true is Wifi Display is enabled, false otherwise. */ isEnabled()247 public boolean isEnabled() { 248 return mEnabled; 249 } 250 251 /** Returns true is Wifi Display R2 is enabled, false otherwise. */ isR2Supported()252 public boolean isR2Supported() { 253 return mR2DeviceInfo >= 0; 254 } 255 256 /** 257 * Sets whether Wifi Display should be enabled. 258 * 259 * @param enabled true to enable Wifi Display, false to disable 260 */ setEnabled(boolean enabled)261 public void setEnabled(boolean enabled) { 262 mEnabled = enabled; 263 } 264 265 /** 266 * Sets the type of the Wifi Display R2 device. 267 * See Wifi Display technical specification v2.0.0, section 5.1.12 for Wifi Display R2. 268 * Before calling this API, call {@link WifiManager#isWifiDisplayR2Supported() 269 * to know whether Wifi Display R2 is supported or not. 270 * If R2 info was filled without Wifi Display R2 support, 271 * {@link WifiP2pManager#setWfdInfo(Channel, WifiP2pWfdInfo, ActionListener) 272 * would fail. 273 * 274 * @param deviceType One of {@link #DEVICE_TYPE_WFD_SOURCE}, {@link #DEVICE_TYPE_PRIMARY_SINK}, 275 * {@link #DEVICE_TYPE_SOURCE_OR_PRIMARY_SINK} 276 * @return true if the device type was successfully set, false otherwise 277 */ 278 @RequiresApi(Build.VERSION_CODES.S) setR2DeviceType(@eviceType int deviceType)279 public boolean setR2DeviceType(@DeviceType int deviceType) { 280 if (!SdkLevel.isAtLeastS()) { 281 throw new UnsupportedOperationException(); 282 } 283 if (DEVICE_TYPE_WFD_SOURCE != deviceType 284 && DEVICE_TYPE_PRIMARY_SINK != deviceType 285 && DEVICE_TYPE_SOURCE_OR_PRIMARY_SINK != deviceType) { 286 return false; 287 } 288 if (!isR2Supported()) mR2DeviceInfo = 0; 289 mR2DeviceInfo &= ~DEVICE_INFO_DEVICE_TYPE_MASK; 290 mR2DeviceInfo |= deviceType; 291 return true; 292 } 293 294 /** 295 * Get the type of the device. 296 * One of {@link #DEVICE_TYPE_WFD_SOURCE}, {@link #DEVICE_TYPE_PRIMARY_SINK}, 297 * {@link #DEVICE_TYPE_SECONDARY_SINK}, {@link #DEVICE_TYPE_SOURCE_OR_PRIMARY_SINK} 298 */ 299 @DeviceType getDeviceType()300 public int getDeviceType() { 301 return mDeviceInfo & DEVICE_INFO_DEVICE_TYPE_MASK; 302 } 303 304 /** 305 * Get the type of the R2 device. 306 * One of {@link #DEVICE_TYPE_WFD_SOURCE}, {@link #DEVICE_TYPE_PRIMARY_SINK}, 307 * or {@link #DEVICE_TYPE_SOURCE_OR_PRIMARY_SINK} 308 */ 309 @DeviceType getR2DeviceType()310 public int getR2DeviceType() { 311 return mR2DeviceInfo & DEVICE_INFO_DEVICE_TYPE_MASK; 312 } 313 314 /** 315 * Sets the type of the device. 316 * 317 * @param deviceType One of {@link #DEVICE_TYPE_WFD_SOURCE}, {@link #DEVICE_TYPE_PRIMARY_SINK}, 318 * {@link #DEVICE_TYPE_SECONDARY_SINK}, {@link #DEVICE_TYPE_SOURCE_OR_PRIMARY_SINK} 319 * @return true if the device type was successfully set, false otherwise 320 */ setDeviceType(@eviceType int deviceType)321 public boolean setDeviceType(@DeviceType int deviceType) { 322 if (DEVICE_TYPE_WFD_SOURCE <= deviceType 323 && deviceType <= DEVICE_TYPE_SOURCE_OR_PRIMARY_SINK) { 324 mDeviceInfo &= ~DEVICE_INFO_DEVICE_TYPE_MASK; 325 mDeviceInfo |= deviceType; 326 return true; 327 } 328 return false; 329 } 330 331 /** Returns true if a session is available, false otherwise. */ isSessionAvailable()332 public boolean isSessionAvailable() { 333 return (mDeviceInfo & DEVICE_INFO_SESSION_AVAILABLE_MASK) != 0; 334 } 335 336 /** 337 * Sets whether a session is available. 338 * 339 * @param enabled true to indicate that a session is available, false otherwise. 340 */ setSessionAvailable(boolean enabled)341 public void setSessionAvailable(boolean enabled) { 342 if (enabled) { 343 mDeviceInfo |= SESSION_AVAILABLE_BIT1; 344 mDeviceInfo &= ~SESSION_AVAILABLE_BIT2; 345 } else { 346 mDeviceInfo &= ~DEVICE_INFO_SESSION_AVAILABLE_MASK; 347 } 348 } 349 350 /** 351 * @return true if Content Protection using the HDCP system 2.0/2.1 is supported. 352 */ isContentProtectionSupported()353 public boolean isContentProtectionSupported() { 354 return (mDeviceInfo & DEVICE_INFO_CONTENT_PROTECTION_SUPPORT) != 0; 355 } 356 357 /** 358 * Sets whether Content Protection using the HDCP system 2.0/2.1 is supported. 359 * 360 * @param enabled true to indicate that Content Protection is supported, false otherwise. 361 */ setContentProtectionSupported(boolean enabled)362 public void setContentProtectionSupported(boolean enabled) { 363 if (enabled) { 364 mDeviceInfo |= DEVICE_INFO_CONTENT_PROTECTION_SUPPORT; 365 } else { 366 mDeviceInfo &= ~DEVICE_INFO_CONTENT_PROTECTION_SUPPORT; 367 } 368 } 369 370 /** 371 * Returns true if Coupled Sink is supported by WFD Source. 372 * See Wifi Display technical specification v1.0.0, section 4.9. 373 */ isCoupledSinkSupportedAtSource()374 public boolean isCoupledSinkSupportedAtSource() { 375 return (mDeviceInfo & DEVICE_INFO_COUPLED_SINK_SUPPORT_AT_SOURCE) != 0; 376 } 377 378 /** 379 * Sets whether Coupled Sink feature is supported by WFD Source. 380 * See Wifi Display technical specification v1.0.0, section 4.9. 381 * 382 * @param enabled true to indicate support for coupled sink, false otherwise. 383 */ setCoupledSinkSupportAtSource(boolean enabled)384 public void setCoupledSinkSupportAtSource(boolean enabled) { 385 if (enabled) { 386 mDeviceInfo |= DEVICE_INFO_COUPLED_SINK_SUPPORT_AT_SOURCE; 387 } else { 388 mDeviceInfo &= ~DEVICE_INFO_COUPLED_SINK_SUPPORT_AT_SOURCE; 389 } 390 } 391 392 /** 393 * Returns true if Coupled Sink is supported by WFD Sink. 394 * See Wifi Display technical specification v1.0.0, section 4.9. 395 */ isCoupledSinkSupportedAtSink()396 public boolean isCoupledSinkSupportedAtSink() { 397 return (mDeviceInfo & DEVICE_INFO_COUPLED_SINK_SUPPORT_AT_SINK) != 0; 398 } 399 400 /** 401 * Sets whether Coupled Sink feature is supported by WFD Sink. 402 * See Wifi Display technical specification v1.0.0, section 4.9. 403 * 404 * @param enabled true to indicate support for coupled sink, false otherwise. 405 */ setCoupledSinkSupportAtSink(boolean enabled)406 public void setCoupledSinkSupportAtSink(boolean enabled) { 407 if (enabled) { 408 mDeviceInfo |= DEVICE_INFO_COUPLED_SINK_SUPPORT_AT_SINK; 409 } else { 410 mDeviceInfo &= ~DEVICE_INFO_COUPLED_SINK_SUPPORT_AT_SINK; 411 } 412 } 413 414 /** Returns the TCP port at which the WFD Device listens for RTSP messages. */ getControlPort()415 public int getControlPort() { 416 return mCtrlPort; 417 } 418 419 /** Sets the TCP port at which the WFD Device listens for RTSP messages. */ setControlPort(@ntRangefrom = 0) int port)420 public void setControlPort(@IntRange(from = 0) int port) { 421 mCtrlPort = port; 422 } 423 424 /** Sets the maximum average throughput capability of the WFD Device, in megabits/second. */ setMaxThroughput(@ntRangefrom = 0) int maxThroughput)425 public void setMaxThroughput(@IntRange(from = 0) int maxThroughput) { 426 mMaxThroughput = maxThroughput; 427 } 428 429 /** Returns the maximum average throughput capability of the WFD Device, in megabits/second. */ getMaxThroughput()430 public int getMaxThroughput() { 431 return mMaxThroughput; 432 } 433 434 /** @hide */ getDeviceInfoHex()435 public String getDeviceInfoHex() { 436 return String.format( 437 Locale.US, "%04x%04x%04x", mDeviceInfo, mCtrlPort, mMaxThroughput); 438 } 439 440 /** @hide */ getR2DeviceInfoHex()441 public String getR2DeviceInfoHex() { 442 return String.format(Locale.US, "%04x%04x", 2, mR2DeviceInfo); 443 } 444 445 @Override toString()446 public String toString() { 447 StringBuffer sbuf = new StringBuffer(); 448 sbuf.append("WFD enabled: ").append(mEnabled); 449 sbuf.append("WFD DeviceInfo: ").append(mDeviceInfo); 450 sbuf.append("\n WFD CtrlPort: ").append(mCtrlPort); 451 sbuf.append("\n WFD MaxThroughput: ").append(mMaxThroughput); 452 sbuf.append("\n WFD R2 DeviceInfo: ").append(mR2DeviceInfo); 453 return sbuf.toString(); 454 } 455 456 /** Implement the Parcelable interface */ describeContents()457 public int describeContents() { 458 return 0; 459 } 460 461 /** Copy constructor. */ WifiP2pWfdInfo(@ullable WifiP2pWfdInfo source)462 public WifiP2pWfdInfo(@Nullable WifiP2pWfdInfo source) { 463 if (source != null) { 464 mEnabled = source.mEnabled; 465 mDeviceInfo = source.mDeviceInfo; 466 mCtrlPort = source.mCtrlPort; 467 mMaxThroughput = source.mMaxThroughput; 468 mR2DeviceInfo = source.mR2DeviceInfo; 469 } 470 } 471 472 /** Implement the Parcelable interface */ 473 @Override writeToParcel(@onNull Parcel dest, int flags)474 public void writeToParcel(@NonNull Parcel dest, int flags) { 475 dest.writeInt(mEnabled ? 1 : 0); 476 dest.writeInt(mDeviceInfo); 477 dest.writeInt(mCtrlPort); 478 dest.writeInt(mMaxThroughput); 479 dest.writeInt(mR2DeviceInfo); 480 } 481 readFromParcel(Parcel in)482 private void readFromParcel(Parcel in) { 483 mEnabled = (in.readInt() == 1); 484 mDeviceInfo = in.readInt(); 485 mCtrlPort = in.readInt(); 486 mMaxThroughput = in.readInt(); 487 mR2DeviceInfo = in.readInt(); 488 } 489 490 /** Implement the Parcelable interface */ 491 public static final @NonNull Creator<WifiP2pWfdInfo> CREATOR = 492 new Creator<WifiP2pWfdInfo>() { 493 public WifiP2pWfdInfo createFromParcel(Parcel in) { 494 WifiP2pWfdInfo device = new WifiP2pWfdInfo(); 495 device.readFromParcel(in); 496 return device; 497 } 498 499 public WifiP2pWfdInfo[] newArray(int size) { 500 return new WifiP2pWfdInfo[size]; 501 } 502 }; 503 } 504