| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.net.wifi.p2p; |
| |
| import android.annotation.IntDef; |
| import android.annotation.IntRange; |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| import android.compat.annotation.UnsupportedAppUsage; |
| import android.os.Build; |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| |
| import androidx.annotation.RequiresApi; |
| |
| import com.android.modules.utils.build.SdkLevel; |
| |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.util.Locale; |
| |
| /** |
| * A class representing Wifi Display information for a device. |
| * |
| * See Wifi Display technical specification v1.0.0, section 5.1.2. |
| * See Wifi Display technical specification v2.0.0, section 5.1.12 for Wifi Display R2. |
| */ |
| public final class WifiP2pWfdInfo implements Parcelable { |
| |
| private boolean mEnabled; |
| |
| /** Device information bitmap */ |
| private int mDeviceInfo; |
| |
| /** R2 Device information bitmap */ |
| private int mR2DeviceInfo = -1; |
| |
| /** @hide */ |
| @Retention(RetentionPolicy.SOURCE) |
| @IntDef(prefix = { "DEVICE_TYPE_" }, value = { |
| DEVICE_TYPE_WFD_SOURCE, |
| DEVICE_TYPE_PRIMARY_SINK, |
| DEVICE_TYPE_SECONDARY_SINK, |
| DEVICE_TYPE_SOURCE_OR_PRIMARY_SINK}) |
| public @interface DeviceType {} |
| |
| /** The device is a Wifi Display Source. */ |
| public static final int DEVICE_TYPE_WFD_SOURCE = 0; |
| /** The device is a primary sink. */ |
| public static final int DEVICE_TYPE_PRIMARY_SINK = 1; |
| /** The device is a secondary sink. This type is only supported by R1. */ |
| public static final int DEVICE_TYPE_SECONDARY_SINK = 2; |
| /** The device is dual-role capable i.e. either a WFD source or a primary sink. */ |
| public static final int DEVICE_TYPE_SOURCE_OR_PRIMARY_SINK = 3; |
| |
| /** @hide */ |
| @Retention(RetentionPolicy.SOURCE) |
| @IntDef(prefix = { "PREFERRED_CONNECTIVITY_" }, value = { |
| PREFERRED_CONNECTIVITY_P2P, |
| PREFERRED_CONNECTIVITY_TDLS}) |
| public @interface PreferredConnectivity {} |
| |
| /** Wifi Display (WFD) preferred connectivity is Wifi Direct (P2P). */ |
| public static final int PREFERRED_CONNECTIVITY_P2P = 0; |
| /** Wifi Display (WFD) preferred connectivity is TDLS. */ |
| public static final int PREFERRED_CONNECTIVITY_TDLS = 1; |
| |
| /** @hide */ |
| @Retention(RetentionPolicy.SOURCE) |
| @IntDef(flag = true, prefix = {"DEVICE_INFO_"}, value = { |
| DEVICE_INFO_DEVICE_TYPE_MASK, |
| DEVICE_INFO_COUPLED_SINK_SUPPORT_AT_SOURCE, |
| DEVICE_INFO_COUPLED_SINK_SUPPORT_AT_SINK, |
| DEVICE_INFO_SESSION_AVAILABLE_MASK, |
| DEVICE_INFO_WFD_SERVICE_DISCOVERY_SUPPORT, |
| DEVICE_INFO_PREFERRED_CONNECTIVITY_MASK, |
| DEVICE_INFO_CONTENT_PROTECTION_SUPPORT, |
| DEVICE_INFO_TIME_SYNCHRONIZATION_SUPPORT, |
| DEVICE_INFO_AUDIO_UNSUPPORTED_AT_PRIMARY_SINK, |
| DEVICE_INFO_AUDIO_ONLY_SUPPORT_AT_SOURCE, |
| DEVICE_INFO_TDLS_PERSISTENT_GROUP, |
| DEVICE_INFO_TDLS_PERSISTENT_GROUP_REINVOKE}) |
| public @interface DeviceInfoMask {} |
| |
| /** @hide */ |
| @Retention(RetentionPolicy.SOURCE) |
| @IntDef(flag = true, prefix = {"DEVICE_INFO_"}, value = {DEVICE_INFO_DEVICE_TYPE_MASK}) |
| public @interface R2DeviceInfoMask {} |
| |
| /** |
| * {@link #getDeviceInfo()} & {@link #DEVICE_INFO_DEVICE_TYPE_MASK} is one of |
| * {@link #DEVICE_TYPE_WFD_SOURCE}, {@link #DEVICE_TYPE_PRIMARY_SINK}, |
| * {@link #DEVICE_TYPE_SECONDARY_SINK} or {@link #DEVICE_TYPE_SOURCE_OR_PRIMARY_SINK}. |
| * |
| * The bit definition is listed in 5.1.2 WFD Device Information Subelement and |
| * 5.1.12 WFD R2 Device Information Subelement in Wifi Display Technical Specification. |
| */ |
| public static final int DEVICE_INFO_DEVICE_TYPE_MASK = 1 << 1 | 1 << 0; |
| /** |
| * Bit field for {@link #getDeviceInfo()}, indicates that coupled sink is supported at source. |
| * |
| * The bit definition is listed in 5.1.2 WFD Device Information Subelement in |
| * Wifi Display Technical Specification. |
| */ |
| public static final int DEVICE_INFO_COUPLED_SINK_SUPPORT_AT_SOURCE = 1 << 2; |
| /** |
| * Bit field for {@link #getDeviceInfo()}, indicates that coupled sink is supporeted at sink. |
| * |
| * The bit definition is listed in 5.1.2 WFD Device Information Subelement in |
| * Wifi Display Technical Specification. |
| */ |
| public static final int DEVICE_INFO_COUPLED_SINK_SUPPORT_AT_SINK = 1 << 3; |
| private static final int SESSION_AVAILABLE_BIT1 = 1 << 4; |
| private static final int SESSION_AVAILABLE_BIT2 = 1 << 5; |
| /** |
| * Bit field for {@link #getDeviceInfo()}, indicates that Wifi Display session is available. |
| * |
| * The bit definition is listed in 5.1.2 WFD Device Information Subelement in |
| * Wifi Display Technical Specification. |
| */ |
| public static final int DEVICE_INFO_SESSION_AVAILABLE_MASK = |
| SESSION_AVAILABLE_BIT2 | SESSION_AVAILABLE_BIT1; |
| /** |
| * Bit field for {@link #getDeviceInfo()}, indicates that Wifi Display discovery is supported. |
| * |
| * The bit definition is listed in 5.1.2 WFD Device Information Subelement in |
| * Wifi Display Technical Specification. |
| */ |
| public static final int DEVICE_INFO_WFD_SERVICE_DISCOVERY_SUPPORT = 1 << 6; |
| /** |
| * Bit field for {@link #getDeviceInfo()}, indicate the preferred connectifity for Wifi Display. |
| * |
| * The bit definition is listed in 5.1.2 WFD Device Information Subelement in |
| * Wifi Display Technical Specification. |
| * The value is one of {@link #PREFERRED_CONNECTIVITY_P2P} or |
| * {@link #PREFERRED_CONNECTIVITY_TDLS}. |
| */ |
| public static final int DEVICE_INFO_PREFERRED_CONNECTIVITY_MASK = 1 << 7; |
| /** |
| * Bit field for {@link #getDeviceInfo()}, indicate the support of Content Protection |
| * using the HDCP system 2.0/2.1. |
| * |
| * The bit definition is listed in 5.1.2 WFD Device Information Subelement in |
| * Wifi Display Technical Specification. |
| */ |
| public static final int DEVICE_INFO_CONTENT_PROTECTION_SUPPORT = 1 << 8; |
| /** |
| * Bit field for {@link #getDeviceInfo()}, indicate time synchronization |
| * using 802.1AS is supported. |
| * |
| * The bit definition is listed in 5.1.2 WFD Device Information Subelement in |
| * Wifi Display Technical Specification. |
| */ |
| public static final int DEVICE_INFO_TIME_SYNCHRONIZATION_SUPPORT = 1 << 9; |
| /** |
| * Bit field for {@link #getDeviceInfo()}, indicate audio is not supported at primary sink. |
| * |
| * The bit definition is listed in 5.1.2 WFD Device Information Subelement in |
| * Wifi Display Technical Specification. |
| */ |
| public static final int DEVICE_INFO_AUDIO_UNSUPPORTED_AT_PRIMARY_SINK = 1 << 10; |
| /** |
| * Bit field for {@link #getDeviceInfo()}, indicate audo is only supported at source. |
| * |
| * The bit definition is listed in 5.1.2 WFD Device Information Subelement in |
| * Wifi Display Technical Specification. |
| */ |
| public static final int DEVICE_INFO_AUDIO_ONLY_SUPPORT_AT_SOURCE = 1 << 11; |
| /** Bit field for {@link #getDeviceInfo()}, indicate that TDLS persistent group is intended. |
| * |
| * The bit definition is listed in 5.1.2 WFD Device Information Subelement in |
| * Wifi Display Technical Specification. |
| */ |
| public static final int DEVICE_INFO_TDLS_PERSISTENT_GROUP = 1 << 12; |
| /** Bit field for {@link #getDeviceInfo()}, indicate that the request is for |
| * re-invocation of TDLS persistent group. |
| * |
| * The bit definition is listed in 5.1.2 WFD Device Information Subelement in |
| * Wifi Display Technical Specification. |
| */ |
| public static final int DEVICE_INFO_TDLS_PERSISTENT_GROUP_REINVOKE = 1 << 13; |
| |
| private int mCtrlPort; |
| |
| private int mMaxThroughput; |
| |
| /** Default constructor. */ |
| public WifiP2pWfdInfo() {} |
| |
| /** @hide */ |
| @UnsupportedAppUsage |
| public WifiP2pWfdInfo(int devInfo, int ctrlPort, int maxTput) { |
| mEnabled = true; |
| mDeviceInfo = devInfo; |
| mCtrlPort = ctrlPort; |
| mMaxThroughput = maxTput; |
| mR2DeviceInfo = -1; |
| } |
| |
| /** |
| * Return R1 raw device info, See |
| * Wifi Display technical specification v1.0.0, section 5.1.2. |
| * Access bit fields by DEVICE_INFO_* constants. |
| */ |
| @DeviceInfoMask |
| public int getDeviceInfo() { |
| return mDeviceInfo; |
| } |
| |
| /** |
| * Set Wifi Display R2 raw device info, see |
| * Wifi Display technical specification v2.0.0, section 5.1.12. |
| * Access bit fields by {@link #DEVICE_INFO_DEVICE_TYPE_MASK}. |
| * |
| * @param r2DeviceInfo the raw data of R2 device info. |
| * @hide |
| */ |
| public void setR2DeviceInfo(int r2DeviceInfo) { |
| mR2DeviceInfo = r2DeviceInfo; |
| } |
| |
| /** |
| * Return R2 raw device info, See |
| * Wifi Display technical specification v2.0.0, section 5.1.12. |
| * Access bit fields by {@link #DEVICE_INFO_DEVICE_TYPE_MASK}. |
| */ |
| @R2DeviceInfoMask |
| public int getR2DeviceInfo() { |
| return mR2DeviceInfo; |
| } |
| |
| /** Returns true is Wifi Display is enabled, false otherwise. */ |
| public boolean isEnabled() { |
| return mEnabled; |
| } |
| |
| /** Returns true is Wifi Display R2 is enabled, false otherwise. */ |
| public boolean isR2Supported() { |
| return mR2DeviceInfo >= 0; |
| } |
| |
| /** |
| * Sets whether Wifi Display should be enabled. |
| * |
| * @param enabled true to enable Wifi Display, false to disable |
| */ |
| public void setEnabled(boolean enabled) { |
| mEnabled = enabled; |
| } |
| |
| /** |
| * Sets the type of the Wifi Display R2 device. |
| * See Wifi Display technical specification v2.0.0, section 5.1.12 for Wifi Display R2. |
| * Before calling this API, call {@link WifiManager#isWifiDisplayR2Supported() |
| * to know whether Wifi Display R2 is supported or not. |
| * If R2 info was filled without Wifi Display R2 support, |
| * {@link WifiP2pManager#setWfdInfo(Channel, WifiP2pWfdInfo, ActionListener) |
| * would fail. |
| * |
| * @param deviceType One of {@link #DEVICE_TYPE_WFD_SOURCE}, {@link #DEVICE_TYPE_PRIMARY_SINK}, |
| * {@link #DEVICE_TYPE_SOURCE_OR_PRIMARY_SINK} |
| * @return true if the device type was successfully set, false otherwise |
| */ |
| @RequiresApi(Build.VERSION_CODES.S) |
| public boolean setR2DeviceType(@DeviceType int deviceType) { |
| if (!SdkLevel.isAtLeastS()) { |
| throw new UnsupportedOperationException(); |
| } |
| if (DEVICE_TYPE_WFD_SOURCE != deviceType |
| && DEVICE_TYPE_PRIMARY_SINK != deviceType |
| && DEVICE_TYPE_SOURCE_OR_PRIMARY_SINK != deviceType) { |
| return false; |
| } |
| if (!isR2Supported()) mR2DeviceInfo = 0; |
| mR2DeviceInfo &= ~DEVICE_INFO_DEVICE_TYPE_MASK; |
| mR2DeviceInfo |= deviceType; |
| return true; |
| } |
| |
| /** |
| * Get the type of the device. |
| * One of {@link #DEVICE_TYPE_WFD_SOURCE}, {@link #DEVICE_TYPE_PRIMARY_SINK}, |
| * {@link #DEVICE_TYPE_SECONDARY_SINK}, {@link #DEVICE_TYPE_SOURCE_OR_PRIMARY_SINK} |
| */ |
| @DeviceType |
| public int getDeviceType() { |
| return mDeviceInfo & DEVICE_INFO_DEVICE_TYPE_MASK; |
| } |
| |
| /** |
| * Get the type of the R2 device. |
| * One of {@link #DEVICE_TYPE_WFD_SOURCE}, {@link #DEVICE_TYPE_PRIMARY_SINK}, |
| * or {@link #DEVICE_TYPE_SOURCE_OR_PRIMARY_SINK} |
| */ |
| @DeviceType |
| public int getR2DeviceType() { |
| return mR2DeviceInfo & DEVICE_INFO_DEVICE_TYPE_MASK; |
| } |
| |
| /** |
| * Sets the type of the device. |
| * |
| * @param deviceType One of {@link #DEVICE_TYPE_WFD_SOURCE}, {@link #DEVICE_TYPE_PRIMARY_SINK}, |
| * {@link #DEVICE_TYPE_SECONDARY_SINK}, {@link #DEVICE_TYPE_SOURCE_OR_PRIMARY_SINK} |
| * @return true if the device type was successfully set, false otherwise |
| */ |
| public boolean setDeviceType(@DeviceType int deviceType) { |
| if (DEVICE_TYPE_WFD_SOURCE <= deviceType |
| && deviceType <= DEVICE_TYPE_SOURCE_OR_PRIMARY_SINK) { |
| mDeviceInfo &= ~DEVICE_INFO_DEVICE_TYPE_MASK; |
| mDeviceInfo |= deviceType; |
| return true; |
| } |
| return false; |
| } |
| |
| /** Returns true if a session is available, false otherwise. */ |
| public boolean isSessionAvailable() { |
| return (mDeviceInfo & DEVICE_INFO_SESSION_AVAILABLE_MASK) != 0; |
| } |
| |
| /** |
| * Sets whether a session is available. |
| * |
| * @param enabled true to indicate that a session is available, false otherwise. |
| */ |
| public void setSessionAvailable(boolean enabled) { |
| if (enabled) { |
| mDeviceInfo |= SESSION_AVAILABLE_BIT1; |
| mDeviceInfo &= ~SESSION_AVAILABLE_BIT2; |
| } else { |
| mDeviceInfo &= ~DEVICE_INFO_SESSION_AVAILABLE_MASK; |
| } |
| } |
| |
| /** |
| * @return true if Content Protection using the HDCP system 2.0/2.1 is supported. |
| */ |
| public boolean isContentProtectionSupported() { |
| return (mDeviceInfo & DEVICE_INFO_CONTENT_PROTECTION_SUPPORT) != 0; |
| } |
| |
| /** |
| * Sets whether Content Protection using the HDCP system 2.0/2.1 is supported. |
| * |
| * @param enabled true to indicate that Content Protection is supported, false otherwise. |
| */ |
| public void setContentProtectionSupported(boolean enabled) { |
| if (enabled) { |
| mDeviceInfo |= DEVICE_INFO_CONTENT_PROTECTION_SUPPORT; |
| } else { |
| mDeviceInfo &= ~DEVICE_INFO_CONTENT_PROTECTION_SUPPORT; |
| } |
| } |
| |
| /** |
| * Returns true if Coupled Sink is supported by WFD Source. |
| * See Wifi Display technical specification v1.0.0, section 4.9. |
| */ |
| public boolean isCoupledSinkSupportedAtSource() { |
| return (mDeviceInfo & DEVICE_INFO_COUPLED_SINK_SUPPORT_AT_SOURCE) != 0; |
| } |
| |
| /** |
| * Sets whether Coupled Sink feature is supported by WFD Source. |
| * See Wifi Display technical specification v1.0.0, section 4.9. |
| * |
| * @param enabled true to indicate support for coupled sink, false otherwise. |
| */ |
| public void setCoupledSinkSupportAtSource(boolean enabled) { |
| if (enabled) { |
| mDeviceInfo |= DEVICE_INFO_COUPLED_SINK_SUPPORT_AT_SOURCE; |
| } else { |
| mDeviceInfo &= ~DEVICE_INFO_COUPLED_SINK_SUPPORT_AT_SOURCE; |
| } |
| } |
| |
| /** |
| * Returns true if Coupled Sink is supported by WFD Sink. |
| * See Wifi Display technical specification v1.0.0, section 4.9. |
| */ |
| public boolean isCoupledSinkSupportedAtSink() { |
| return (mDeviceInfo & DEVICE_INFO_COUPLED_SINK_SUPPORT_AT_SINK) != 0; |
| } |
| |
| /** |
| * Sets whether Coupled Sink feature is supported by WFD Sink. |
| * See Wifi Display technical specification v1.0.0, section 4.9. |
| * |
| * @param enabled true to indicate support for coupled sink, false otherwise. |
| */ |
| public void setCoupledSinkSupportAtSink(boolean enabled) { |
| if (enabled) { |
| mDeviceInfo |= DEVICE_INFO_COUPLED_SINK_SUPPORT_AT_SINK; |
| } else { |
| mDeviceInfo &= ~DEVICE_INFO_COUPLED_SINK_SUPPORT_AT_SINK; |
| } |
| } |
| |
| /** Returns the TCP port at which the WFD Device listens for RTSP messages. */ |
| public int getControlPort() { |
| return mCtrlPort; |
| } |
| |
| /** Sets the TCP port at which the WFD Device listens for RTSP messages. */ |
| public void setControlPort(@IntRange(from = 0) int port) { |
| mCtrlPort = port; |
| } |
| |
| /** Sets the maximum average throughput capability of the WFD Device, in megabits/second. */ |
| public void setMaxThroughput(@IntRange(from = 0) int maxThroughput) { |
| mMaxThroughput = maxThroughput; |
| } |
| |
| /** Returns the maximum average throughput capability of the WFD Device, in megabits/second. */ |
| public int getMaxThroughput() { |
| return mMaxThroughput; |
| } |
| |
| /** @hide */ |
| public String getDeviceInfoHex() { |
| return String.format( |
| Locale.US, "%04x%04x%04x", mDeviceInfo, mCtrlPort, mMaxThroughput); |
| } |
| |
| /** @hide */ |
| public String getR2DeviceInfoHex() { |
| return String.format(Locale.US, "%04x%04x", 2, mR2DeviceInfo); |
| } |
| |
| @Override |
| public String toString() { |
| StringBuffer sbuf = new StringBuffer(); |
| sbuf.append("WFD enabled: ").append(mEnabled); |
| sbuf.append("WFD DeviceInfo: ").append(mDeviceInfo); |
| sbuf.append("\n WFD CtrlPort: ").append(mCtrlPort); |
| sbuf.append("\n WFD MaxThroughput: ").append(mMaxThroughput); |
| sbuf.append("\n WFD R2 DeviceInfo: ").append(mR2DeviceInfo); |
| return sbuf.toString(); |
| } |
| |
| /** Implement the Parcelable interface */ |
| public int describeContents() { |
| return 0; |
| } |
| |
| /** Copy constructor. */ |
| public WifiP2pWfdInfo(@Nullable WifiP2pWfdInfo source) { |
| if (source != null) { |
| mEnabled = source.mEnabled; |
| mDeviceInfo = source.mDeviceInfo; |
| mCtrlPort = source.mCtrlPort; |
| mMaxThroughput = source.mMaxThroughput; |
| mR2DeviceInfo = source.mR2DeviceInfo; |
| } |
| } |
| |
| /** Implement the Parcelable interface */ |
| @Override |
| public void writeToParcel(@NonNull Parcel dest, int flags) { |
| dest.writeInt(mEnabled ? 1 : 0); |
| dest.writeInt(mDeviceInfo); |
| dest.writeInt(mCtrlPort); |
| dest.writeInt(mMaxThroughput); |
| dest.writeInt(mR2DeviceInfo); |
| } |
| |
| private void readFromParcel(Parcel in) { |
| mEnabled = (in.readInt() == 1); |
| mDeviceInfo = in.readInt(); |
| mCtrlPort = in.readInt(); |
| mMaxThroughput = in.readInt(); |
| mR2DeviceInfo = in.readInt(); |
| } |
| |
| /** Implement the Parcelable interface */ |
| public static final @NonNull Creator<WifiP2pWfdInfo> CREATOR = |
| new Creator<WifiP2pWfdInfo>() { |
| public WifiP2pWfdInfo createFromParcel(Parcel in) { |
| WifiP2pWfdInfo device = new WifiP2pWfdInfo(); |
| device.readFromParcel(in); |
| return device; |
| } |
| |
| public WifiP2pWfdInfo[] newArray(int size) { |
| return new WifiP2pWfdInfo[size]; |
| } |
| }; |
| } |