1 /* 2 * Copyright (C) 2016 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.aware; 18 19 import android.os.Parcel; 20 import android.os.Parcelable; 21 22 import java.util.Arrays; 23 24 /** 25 * Defines a request object to configure a Wi-Fi Aware network. Built using 26 * {@link ConfigRequest.Builder}. Configuration is requested using 27 * {@link WifiAwareManager#attach(AttachCallback, android.os.Handler)}. 28 * Note that the actual achieved configuration may be different from the 29 * requested configuration - since different applications may request different 30 * configurations. 31 * 32 * @hide 33 */ 34 public final class ConfigRequest implements Parcelable { 35 /** 36 * Lower range of possible cluster ID. 37 */ 38 public static final int CLUSTER_ID_MIN = 0; 39 40 /** 41 * Upper range of possible cluster ID. 42 */ 43 public static final int CLUSTER_ID_MAX = 0xFFFF; 44 45 /** 46 * Indices for configuration variables which are specified per band. 47 */ 48 public static final int NAN_BAND_24GHZ = 0; 49 public static final int NAN_BAND_5GHZ = 1; 50 public static final int NAN_BAND_6GHZ = 2; 51 52 /** 53 * Magic values for Discovery Window (DW) interval configuration 54 */ 55 public static final int DW_INTERVAL_NOT_INIT = -1; 56 public static final int DW_DISABLE = 0; // only valid for 5GHz 57 58 /** 59 * Indicates whether 5G band support is requested. 60 */ 61 public final boolean mSupport5gBand; 62 63 /** 64 * Indicates whether 6G band support is requested. 65 */ 66 public final boolean mSupport6gBand; 67 68 /** 69 * Specifies the desired master preference. 70 */ 71 public final int mMasterPreference; 72 73 /** 74 * Specifies the desired lower range of the cluster ID. Must be lower then 75 * {@link ConfigRequest#mClusterHigh}. 76 */ 77 public final int mClusterLow; 78 79 /** 80 * Specifies the desired higher range of the cluster ID. Must be higher then 81 * {@link ConfigRequest#mClusterLow}. 82 */ 83 public final int mClusterHigh; 84 85 /** 86 * Specifies the discovery window interval for the device on NAN_BAND_*. 87 */ 88 public final int mDiscoveryWindowInterval[]; 89 ConfigRequest(boolean support5gBand, boolean support6gBand, int masterPreference, int clusterLow, int clusterHigh, int[] discoveryWindowInterval)90 private ConfigRequest(boolean support5gBand, boolean support6gBand, int masterPreference, 91 int clusterLow, int clusterHigh, int[] discoveryWindowInterval) { 92 mSupport5gBand = support5gBand; 93 mSupport6gBand = support6gBand; 94 mMasterPreference = masterPreference; 95 mClusterLow = clusterLow; 96 mClusterHigh = clusterHigh; 97 mDiscoveryWindowInterval = discoveryWindowInterval; 98 } 99 100 @Override toString()101 public String toString() { 102 return "ConfigRequest [mSupport5gBand=" + mSupport5gBand 103 + ", mSupport6gBand=" + mSupport6gBand 104 + ", mMasterPreference=" + mMasterPreference 105 + ", mClusterLow=" + mClusterLow 106 + ", mClusterHigh=" + mClusterHigh 107 + ", mDiscoveryWindowInterval=" + Arrays.toString(mDiscoveryWindowInterval) + "]"; 108 } 109 110 @Override describeContents()111 public int describeContents() { 112 return 0; 113 } 114 115 @Override writeToParcel(Parcel dest, int flags)116 public void writeToParcel(Parcel dest, int flags) { 117 dest.writeInt(mSupport5gBand ? 1 : 0); 118 dest.writeInt(mSupport6gBand ? 1 : 0); 119 dest.writeInt(mMasterPreference); 120 dest.writeInt(mClusterLow); 121 dest.writeInt(mClusterHigh); 122 dest.writeIntArray(mDiscoveryWindowInterval); 123 } 124 125 public static final @android.annotation.NonNull Creator<ConfigRequest> CREATOR = new Creator<ConfigRequest>() { 126 @Override 127 public ConfigRequest[] newArray(int size) { 128 return new ConfigRequest[size]; 129 } 130 131 @Override 132 public ConfigRequest createFromParcel(Parcel in) { 133 boolean support5gBand = in.readInt() != 0; 134 boolean support6gBand = in.readInt() != 0; 135 int masterPreference = in.readInt(); 136 int clusterLow = in.readInt(); 137 int clusterHigh = in.readInt(); 138 int discoveryWindowInterval[] = in.createIntArray(); 139 140 return new ConfigRequest(support5gBand, support6gBand, masterPreference, clusterLow, 141 clusterHigh, discoveryWindowInterval); 142 } 143 }; 144 145 @Override equals(Object o)146 public boolean equals(Object o) { 147 if (this == o) { 148 return true; 149 } 150 151 if (!(o instanceof ConfigRequest)) { 152 return false; 153 } 154 155 ConfigRequest lhs = (ConfigRequest) o; 156 157 return mSupport5gBand == lhs.mSupport5gBand 158 && mSupport6gBand == lhs.mSupport6gBand 159 && mMasterPreference == lhs.mMasterPreference 160 && mClusterLow == lhs.mClusterLow && mClusterHigh == lhs.mClusterHigh 161 && Arrays.equals(mDiscoveryWindowInterval, lhs.mDiscoveryWindowInterval); 162 } 163 164 @Override hashCode()165 public int hashCode() { 166 int result = 17; 167 168 result = 31 * result + (mSupport5gBand ? 1 : 0); 169 result = 31 * result + (mSupport6gBand ? 1 : 0); 170 result = 31 * result + mMasterPreference; 171 result = 31 * result + mClusterLow; 172 result = 31 * result + mClusterHigh; 173 result = 31 * result + Arrays.hashCode(mDiscoveryWindowInterval); 174 175 return result; 176 } 177 178 /** 179 * Verifies that the contents of the ConfigRequest are valid. Otherwise 180 * throws an IllegalArgumentException. 181 */ validate()182 public void validate() throws IllegalArgumentException { 183 if (mMasterPreference < 0) { 184 throw new IllegalArgumentException( 185 "Master Preference specification must be non-negative"); 186 } 187 if (mMasterPreference == 1 || mMasterPreference == 255 || mMasterPreference > 255) { 188 throw new IllegalArgumentException("Master Preference specification must not " 189 + "exceed 255 or use 1 or 255 (reserved values)"); 190 } 191 if (mClusterLow < CLUSTER_ID_MIN) { 192 throw new IllegalArgumentException("Cluster specification must be non-negative"); 193 } 194 if (mClusterLow > CLUSTER_ID_MAX) { 195 throw new IllegalArgumentException("Cluster specification must not exceed 0xFFFF"); 196 } 197 if (mClusterHigh < CLUSTER_ID_MIN) { 198 throw new IllegalArgumentException("Cluster specification must be non-negative"); 199 } 200 if (mClusterHigh > CLUSTER_ID_MAX) { 201 throw new IllegalArgumentException("Cluster specification must not exceed 0xFFFF"); 202 } 203 if (mClusterLow > mClusterHigh) { 204 throw new IllegalArgumentException( 205 "Invalid argument combination - must have Cluster Low <= Cluster High"); 206 } 207 if (mDiscoveryWindowInterval.length != 3) { 208 throw new IllegalArgumentException( 209 "Invalid discovery window interval: must have 3 elements (2.4 & 5 & 6"); 210 } 211 if (mDiscoveryWindowInterval[NAN_BAND_24GHZ] != DW_INTERVAL_NOT_INIT && 212 (mDiscoveryWindowInterval[NAN_BAND_24GHZ] < 1 // valid for 2.4GHz: [1-5] 213 || mDiscoveryWindowInterval[NAN_BAND_24GHZ] > 5)) { 214 throw new IllegalArgumentException( 215 "Invalid discovery window interval for 2.4GHz: valid is UNSET or [1,5]"); 216 } 217 if (mDiscoveryWindowInterval[NAN_BAND_5GHZ] != DW_INTERVAL_NOT_INIT && 218 (mDiscoveryWindowInterval[NAN_BAND_5GHZ] < 0 // valid for 5GHz: [0-5] 219 || mDiscoveryWindowInterval[NAN_BAND_5GHZ] > 5)) { 220 throw new IllegalArgumentException( 221 "Invalid discovery window interval for 5GHz: valid is UNSET or [0,5]"); 222 } 223 if (mDiscoveryWindowInterval[NAN_BAND_6GHZ] != DW_INTERVAL_NOT_INIT 224 && (mDiscoveryWindowInterval[NAN_BAND_6GHZ] < 0 // valid for 6GHz: [0-5] 225 || mDiscoveryWindowInterval[NAN_BAND_6GHZ] > 5)) { 226 throw new IllegalArgumentException( 227 "Invalid discovery window interval for 6GHz: valid is UNSET or [0,5]"); 228 } 229 } 230 231 /** 232 * Builder used to build {@link ConfigRequest} objects. 233 */ 234 public static final class Builder { 235 private boolean mSupport5gBand = true; 236 private boolean mSupport6gBand = false; 237 private int mMasterPreference = 0; 238 private int mClusterLow = CLUSTER_ID_MIN; 239 private int mClusterHigh = CLUSTER_ID_MAX; 240 private int[] mDiscoveryWindowInterval = {DW_INTERVAL_NOT_INIT, DW_INTERVAL_NOT_INIT, 241 DW_INTERVAL_NOT_INIT}; 242 243 /** 244 * Specify whether 5G band support is required in this request. Disabled by default. 245 * 246 * @param support5gBand Support for 5G band is required. 247 * 248 * @return The builder to facilitate chaining 249 * {@code builder.setXXX(..).setXXX(..)}. 250 */ setSupport5gBand(boolean support5gBand)251 public Builder setSupport5gBand(boolean support5gBand) { 252 mSupport5gBand = support5gBand; 253 return this; 254 } 255 256 /** 257 * Specify whether 6G band support is required in this request. Disabled by default. 258 * 259 * @param support6gBand Support for 6G band is required. 260 * 261 * @return The builder to facilitate chaining 262 * {@code builder.setXXX(..).setXXX(..)}. 263 */ setSupport6gBand(boolean support6gBand)264 public Builder setSupport6gBand(boolean support6gBand) { 265 mSupport6gBand = support6gBand; 266 return this; 267 } 268 269 /** 270 * Specify the Master Preference requested. The permitted range is 0 (the default) to 271 * 255 with 1 and 255 excluded (reserved). 272 * 273 * @param masterPreference The requested master preference 274 * 275 * @return The builder to facilitate chaining 276 * {@code builder.setXXX(..).setXXX(..)}. 277 */ setMasterPreference(int masterPreference)278 public Builder setMasterPreference(int masterPreference) { 279 if (masterPreference < 0) { 280 throw new IllegalArgumentException( 281 "Master Preference specification must be non-negative"); 282 } 283 if (masterPreference == 1 || masterPreference == 255 || masterPreference > 255) { 284 throw new IllegalArgumentException("Master Preference specification must not " 285 + "exceed 255 or use 1 or 255 (reserved values)"); 286 } 287 288 mMasterPreference = masterPreference; 289 return this; 290 } 291 292 /** 293 * The Cluster ID is generated randomly for new Aware networks. Specify 294 * the lower range of the cluster ID. The upper range is specified using 295 * the {@link ConfigRequest.Builder#setClusterHigh(int)}. The permitted 296 * range is 0 (the default) to the value specified by 297 * {@link ConfigRequest.Builder#setClusterHigh(int)}. Equality of Low and High is 298 * permitted which restricts the Cluster ID to the specified value. 299 * 300 * @param clusterLow The lower range of the generated cluster ID. 301 * 302 * @return The builder to facilitate chaining 303 * {@code builder.setClusterLow(..).setClusterHigh(..)}. 304 */ setClusterLow(int clusterLow)305 public Builder setClusterLow(int clusterLow) { 306 if (clusterLow < CLUSTER_ID_MIN) { 307 throw new IllegalArgumentException("Cluster specification must be non-negative"); 308 } 309 if (clusterLow > CLUSTER_ID_MAX) { 310 throw new IllegalArgumentException("Cluster specification must not exceed 0xFFFF"); 311 } 312 313 mClusterLow = clusterLow; 314 return this; 315 } 316 317 /** 318 * The Cluster ID is generated randomly for new Aware networks. Specify 319 * the lower upper of the cluster ID. The lower range is specified using 320 * the {@link ConfigRequest.Builder#setClusterLow(int)}. The permitted 321 * range is the value specified by 322 * {@link ConfigRequest.Builder#setClusterLow(int)} to 0xFFFF (the default). Equality of 323 * Low and High is permitted which restricts the Cluster ID to the specified value. 324 * 325 * @param clusterHigh The upper range of the generated cluster ID. 326 * 327 * @return The builder to facilitate chaining 328 * {@code builder.setClusterLow(..).setClusterHigh(..)}. 329 */ setClusterHigh(int clusterHigh)330 public Builder setClusterHigh(int clusterHigh) { 331 if (clusterHigh < CLUSTER_ID_MIN) { 332 throw new IllegalArgumentException("Cluster specification must be non-negative"); 333 } 334 if (clusterHigh > CLUSTER_ID_MAX) { 335 throw new IllegalArgumentException("Cluster specification must not exceed 0xFFFF"); 336 } 337 338 mClusterHigh = clusterHigh; 339 return this; 340 } 341 342 /** 343 * The discovery window interval specifies the discovery windows in which the device will be 344 * awake. The configuration enables trading off latency vs. power (higher interval means 345 * higher discovery latency but lower power). 346 * 347 * @param band Either {@link #NAN_BAND_24GHZ} or {@link #NAN_BAND_5GHZ} or 348 * {@link #NAN_BAND_6GHZ}. 349 * @param interval A value of 1, 2, 3, 4, or 5 indicating an interval of 2^(interval-1). For 350 * the 5GHz band a value of 0 indicates that the device will not be awake 351 * for any discovery windows. 352 * 353 * @return The builder itself to facilitate chaining operations 354 * {@code builder.setDiscoveryWindowInterval(...).setMasterPreference(...)}. 355 */ setDiscoveryWindowInterval(int band, int interval)356 public Builder setDiscoveryWindowInterval(int band, int interval) { 357 if (band != NAN_BAND_24GHZ && band != NAN_BAND_5GHZ && band != NAN_BAND_6GHZ) { 358 throw new IllegalArgumentException("Invalid band value"); 359 } 360 if ((band == NAN_BAND_24GHZ && (interval < 1 || interval > 5)) 361 || (band == NAN_BAND_5GHZ && (interval < 0 || interval > 5)) 362 || (band == NAN_BAND_6GHZ && (interval < 0 || interval > 5))) { 363 throw new IllegalArgumentException( 364 "Invalid interval value: 2.4 GHz [1,5] or 5GHz/6GHz [0,5]"); 365 } 366 367 mDiscoveryWindowInterval[band] = interval; 368 return this; 369 } 370 371 /** 372 * Build {@link ConfigRequest} given the current requests made on the 373 * builder. 374 */ build()375 public ConfigRequest build() { 376 if (mClusterLow > mClusterHigh) { 377 throw new IllegalArgumentException( 378 "Invalid argument combination - must have Cluster Low <= Cluster High"); 379 } 380 381 return new ConfigRequest(mSupport5gBand, mSupport6gBand, mMasterPreference, mClusterLow, 382 mClusterHigh, mDiscoveryWindowInterval); 383 } 384 } 385 } 386