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