1 /*
2  * Copyright (C) 2023 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.FlaggedApi;
20 import android.annotation.IntRange;
21 import android.annotation.NonNull;
22 import android.annotation.RequiresApi;
23 import android.annotation.SystemApi;
24 import android.net.wifi.OuiKeyedData;
25 import android.os.Build;
26 import android.os.Parcel;
27 import android.os.Parcelable;
28 
29 import com.android.modules.utils.build.SdkLevel;
30 import com.android.wifi.flags.Flags;
31 
32 import java.util.ArrayList;
33 import java.util.List;
34 
35 /**
36  * A class representing a Wi-Fi P2P scan configuration for setting up discovery.
37  */
38 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
39 public final class WifiP2pDiscoveryConfig implements Parcelable {
40     /** Type of this P2P scan. */
41     private final @WifiP2pManager.WifiP2pScanType int mScanType;
42 
43     /** Frequency to scan in MHz. */
44     private final int mFrequencyMhz;
45 
46     /** List of {@link OuiKeyedData} providing vendor-specific configuration data. */
47     private final @NonNull List<OuiKeyedData> mVendorData;
48 
WifiP2pDiscoveryConfig(@ifiP2pManager.WifiP2pScanType int scanType, int frequencyMhz, @NonNull List<OuiKeyedData> vendorData)49     private WifiP2pDiscoveryConfig(@WifiP2pManager.WifiP2pScanType int scanType, int frequencyMhz,
50             @NonNull List<OuiKeyedData> vendorData) {
51         mScanType = scanType;
52         mFrequencyMhz = frequencyMhz;
53         mVendorData = new ArrayList<>(vendorData);
54     }
55 
56     /**
57      * Get the type of this scan. See {@link Builder#Builder(int)}}
58      */
59     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
getScanType()60     public @WifiP2pManager.WifiP2pScanType int getScanType() {
61         return mScanType;
62     }
63 
64     /**
65      * Get the frequency to scan in MHz. See {@link Builder#setFrequencyMhz(int)}
66      */
67     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
getFrequencyMhz()68     public int getFrequencyMhz() {
69         return mFrequencyMhz;
70     }
71 
72     /**
73      * Get the vendor-provided configuration data, if it exists. See {@link
74      * Builder#setVendorData(List)}
75      *
76      * @return Vendor configuration data, or empty list if it does not exist.
77      * @hide
78      */
79     @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
80     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
81     @SystemApi
82     @NonNull
getVendorData()83     public List<OuiKeyedData> getVendorData() {
84         if (!SdkLevel.isAtLeastV()) {
85             throw new UnsupportedOperationException();
86         }
87         return mVendorData;
88     }
89 
90     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
91     @Override
toString()92     public String toString() {
93         StringBuffer sbuf = new StringBuffer();
94         sbuf.append("\n scanType: ").append(mScanType);
95         sbuf.append("\n frequencyMhz: ").append(mFrequencyMhz);
96         sbuf.append("\n vendorData: ").append(mVendorData);
97         return sbuf.toString();
98     }
99 
100     /** Implement the Parcelable interface */
101     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
describeContents()102     public int describeContents() {
103         return 0;
104     }
105 
106     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
107     @Override
writeToParcel(@onNull Parcel dest, int flags)108     public void writeToParcel(@NonNull Parcel dest, int flags) {
109         dest.writeInt(mScanType);
110         dest.writeInt(mFrequencyMhz);
111         dest.writeList(mVendorData);
112     }
113 
114     /* Read List<OuiKeyedData> from Parcel */
115     @NonNull
readOuiKeyedDataList(@onNull Parcel in)116     private static List<OuiKeyedData> readOuiKeyedDataList(@NonNull Parcel in) {
117         List<OuiKeyedData> dataList = new ArrayList<>();
118         if (SdkLevel.isAtLeastT()) {
119             in.readList(dataList, OuiKeyedData.class.getClassLoader(), OuiKeyedData.class);
120         } else {
121             in.readList(dataList, OuiKeyedData.class.getClassLoader());
122         }
123         return dataList;
124     }
125 
126     /** @hide */
WifiP2pDiscoveryConfig(@onNull Parcel in)127     WifiP2pDiscoveryConfig(@NonNull Parcel in) {
128         this.mScanType = in.readInt();
129         this.mFrequencyMhz = in.readInt();
130         this.mVendorData = readOuiKeyedDataList(in);
131     }
132 
133     /** Implement the Parcelable interface */
134     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
135     @NonNull
136     public static final Creator<WifiP2pDiscoveryConfig> CREATOR =
137             new Creator<WifiP2pDiscoveryConfig>() {
138                 public WifiP2pDiscoveryConfig createFromParcel(Parcel in) {
139                     return new WifiP2pDiscoveryConfig(in);
140                 }
141 
142                 public WifiP2pDiscoveryConfig[] newArray(int size) {
143                     return new WifiP2pDiscoveryConfig[size];
144                 }
145             };
146 
147     /**
148      * Builder for {@link WifiP2pDiscoveryConfig}.
149      */
150     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
151     public static final class Builder {
152 
153         private final int mScanType;
154         private int mFrequencyMhz = 0;
155         private @NonNull List<OuiKeyedData> mVendorData = new ArrayList<>();
156 
157         /**
158          * Constructor for {@link Builder}.
159          *
160          * @param scanType Type of this P2P scan.
161          */
162         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
Builder(@ifiP2pManager.WifiP2pScanType int scanType)163         public Builder(@WifiP2pManager.WifiP2pScanType int scanType) {
164             mScanType = scanType;
165         }
166 
167         /**
168          * Set the frequency to scan. Only applicable if the scan type is
169          * {@link WifiP2pManager#WIFI_P2P_SCAN_SINGLE_FREQ}.
170          *
171          * @param frequencyMhz Frequency to scan in MHz.
172          * @return Builder for chaining.
173          */
174         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
175         @NonNull
setFrequencyMhz(@ntRangefrom = 0) int frequencyMhz)176         public Builder setFrequencyMhz(@IntRange(from = 0) int frequencyMhz) {
177             if (frequencyMhz <= 0) {
178                 throw new IllegalArgumentException("Frequency must be greater than 0");
179             }
180             mFrequencyMhz = frequencyMhz;
181             return this;
182         }
183 
184         /**
185          * Set additional vendor-provided configuration data.
186          *
187          * @param vendorData List of {@link android.net.wifi.OuiKeyedData} containing the
188          *                   vendor-provided configuration data. Note that multiple elements with
189          *                   the same OUI are allowed.
190          * @return Builder for chaining.
191          * @hide
192          */
193         @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
194         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
195         @SystemApi
196         @NonNull
setVendorData(@onNull List<OuiKeyedData> vendorData)197         public Builder setVendorData(@NonNull List<OuiKeyedData> vendorData) {
198             if (!SdkLevel.isAtLeastV()) {
199                 throw new UnsupportedOperationException();
200             }
201             if (vendorData == null) {
202                 throw new IllegalArgumentException("setVendorData received a null value");
203             }
204             mVendorData = vendorData;
205             return this;
206         }
207 
208         /**
209          * Build {@link WifiP2pDiscoveryConfig} given the current requests made on the builder.
210          * @return {@link WifiP2pDiscoveryConfig} constructed based on builder method calls.
211          */
212         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
213         @NonNull
build()214         public WifiP2pDiscoveryConfig build() {
215             if (mScanType < WifiP2pManager.WIFI_P2P_SCAN_FULL
216                     || mScanType > WifiP2pManager.WIFI_P2P_SCAN_SINGLE_FREQ) {
217                 throw new IllegalArgumentException("Invalid scan type " + mScanType);
218             }
219             if (mScanType == WifiP2pManager.WIFI_P2P_SCAN_SINGLE_FREQ && mFrequencyMhz == 0) {
220                 throw new IllegalArgumentException(
221                         "Scan type is single frequency, but no frequency was provided");
222             }
223             return new WifiP2pDiscoveryConfig(mScanType, mFrequencyMhz, mVendorData);
224         }
225     }
226 }
227