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.nan; 18 19 import android.os.Parcel; 20 import android.os.Parcelable; 21 22 import java.util.Arrays; 23 24 /** 25 * Defines the data for a NAN subscribe session. Built using 26 * {@link SubscribeData.Builder}. Subscribe is done using 27 * {@link WifiNanManager#subscribe(SubscribeData, SubscribeSettings, WifiNanSessionListener, int)} 28 * or 29 * {@link WifiNanSubscribeSession#subscribe(SubscribeData, SubscribeSettings)}. 30 * @hide PROPOSED_NAN_API 31 */ 32 public class SubscribeData implements Parcelable { 33 /** 34 * @hide 35 */ 36 public final String mServiceName; 37 38 /** 39 * @hide 40 */ 41 public final int mServiceSpecificInfoLength; 42 43 /** 44 * @hide 45 */ 46 public final byte[] mServiceSpecificInfo; 47 48 /** 49 * @hide 50 */ 51 public final int mTxFilterLength; 52 53 /** 54 * @hide 55 */ 56 public final byte[] mTxFilter; 57 58 /** 59 * @hide 60 */ 61 public final int mRxFilterLength; 62 63 /** 64 * @hide 65 */ 66 public final byte[] mRxFilter; 67 SubscribeData(String serviceName, byte[] serviceSpecificInfo, int serviceSpecificInfoLength, byte[] txFilter, int txFilterLength, byte[] rxFilter, int rxFilterLength)68 private SubscribeData(String serviceName, byte[] serviceSpecificInfo, 69 int serviceSpecificInfoLength, byte[] txFilter, int txFilterLength, byte[] rxFilter, 70 int rxFilterLength) { 71 mServiceName = serviceName; 72 mServiceSpecificInfoLength = serviceSpecificInfoLength; 73 mServiceSpecificInfo = serviceSpecificInfo; 74 mTxFilterLength = txFilterLength; 75 mTxFilter = txFilter; 76 mRxFilterLength = rxFilterLength; 77 mRxFilter = rxFilter; 78 } 79 80 @Override toString()81 public String toString() { 82 return "SubscribeData [mServiceName='" + mServiceName + "', mServiceSpecificInfo='" 83 + (new String(mServiceSpecificInfo, 0, mServiceSpecificInfoLength)) 84 + "', mTxFilter=" 85 + (new TlvBufferUtils.TlvIterable(0, 1, mTxFilter, mTxFilterLength)).toString() 86 + ", mRxFilter=" 87 + (new TlvBufferUtils.TlvIterable(0, 1, mRxFilter, mRxFilterLength)).toString() 88 + "']"; 89 } 90 91 @Override describeContents()92 public int describeContents() { 93 return 0; 94 } 95 96 @Override writeToParcel(Parcel dest, int flags)97 public void writeToParcel(Parcel dest, int flags) { 98 dest.writeString(mServiceName); 99 dest.writeInt(mServiceSpecificInfoLength); 100 if (mServiceSpecificInfoLength != 0) { 101 dest.writeByteArray(mServiceSpecificInfo, 0, mServiceSpecificInfoLength); 102 } 103 dest.writeInt(mTxFilterLength); 104 if (mTxFilterLength != 0) { 105 dest.writeByteArray(mTxFilter, 0, mTxFilterLength); 106 } 107 dest.writeInt(mRxFilterLength); 108 if (mRxFilterLength != 0) { 109 dest.writeByteArray(mRxFilter, 0, mRxFilterLength); 110 } 111 } 112 113 public static final Creator<SubscribeData> CREATOR = new Creator<SubscribeData>() { 114 @Override 115 public SubscribeData[] newArray(int size) { 116 return new SubscribeData[size]; 117 } 118 119 @Override 120 public SubscribeData createFromParcel(Parcel in) { 121 String serviceName = in.readString(); 122 int ssiLength = in.readInt(); 123 byte[] ssi = new byte[ssiLength]; 124 if (ssiLength != 0) { 125 in.readByteArray(ssi); 126 } 127 int txFilterLength = in.readInt(); 128 byte[] txFilter = new byte[txFilterLength]; 129 if (txFilterLength != 0) { 130 in.readByteArray(txFilter); 131 } 132 int rxFilterLength = in.readInt(); 133 byte[] rxFilter = new byte[rxFilterLength]; 134 if (rxFilterLength != 0) { 135 in.readByteArray(rxFilter); 136 } 137 138 return new SubscribeData(serviceName, ssi, ssiLength, txFilter, txFilterLength, 139 rxFilter, rxFilterLength); 140 } 141 }; 142 143 @Override equals(Object o)144 public boolean equals(Object o) { 145 if (this == o) { 146 return true; 147 } 148 149 if (!(o instanceof SubscribeData)) { 150 return false; 151 } 152 153 SubscribeData lhs = (SubscribeData) o; 154 155 if (!mServiceName.equals(lhs.mServiceName) 156 || mServiceSpecificInfoLength != lhs.mServiceSpecificInfoLength 157 || mTxFilterLength != lhs.mTxFilterLength 158 || mRxFilterLength != lhs.mRxFilterLength) { 159 return false; 160 } 161 162 if (mServiceSpecificInfo != null && lhs.mServiceSpecificInfo != null) { 163 for (int i = 0; i < mServiceSpecificInfoLength; ++i) { 164 if (mServiceSpecificInfo[i] != lhs.mServiceSpecificInfo[i]) { 165 return false; 166 } 167 } 168 } else if (mServiceSpecificInfoLength != 0) { 169 return false; // invalid != invalid 170 } 171 172 if (mTxFilter != null && lhs.mTxFilter != null) { 173 for (int i = 0; i < mTxFilterLength; ++i) { 174 if (mTxFilter[i] != lhs.mTxFilter[i]) { 175 return false; 176 } 177 } 178 } else if (mTxFilterLength != 0) { 179 return false; // invalid != invalid 180 } 181 182 if (mRxFilter != null && lhs.mRxFilter != null) { 183 for (int i = 0; i < mRxFilterLength; ++i) { 184 if (mRxFilter[i] != lhs.mRxFilter[i]) { 185 return false; 186 } 187 } 188 } else if (mRxFilterLength != 0) { 189 return false; // invalid != invalid 190 } 191 192 return true; 193 } 194 195 @Override hashCode()196 public int hashCode() { 197 int result = 17; 198 199 result = 31 * result + mServiceName.hashCode(); 200 result = 31 * result + mServiceSpecificInfoLength; 201 result = 31 * result + Arrays.hashCode(mServiceSpecificInfo); 202 result = 31 * result + mTxFilterLength; 203 result = 31 * result + Arrays.hashCode(mTxFilter); 204 result = 31 * result + mRxFilterLength; 205 result = 31 * result + Arrays.hashCode(mRxFilter); 206 207 return result; 208 } 209 210 /** 211 * Builder used to build {@link SubscribeData} objects. 212 */ 213 public static final class Builder { 214 private String mServiceName; 215 private int mServiceSpecificInfoLength; 216 private byte[] mServiceSpecificInfo = new byte[0]; 217 private int mTxFilterLength; 218 private byte[] mTxFilter = new byte[0]; 219 private int mRxFilterLength; 220 private byte[] mRxFilter = new byte[0]; 221 222 /** 223 * Specify the service name of the subscribe session. The actual on-air 224 * value is a 6 byte hashed representation of this string. 225 * 226 * @param serviceName The service name for the subscribe session. 227 * @return The builder to facilitate chaining 228 * {@code builder.setXXX(..).setXXX(..)}. 229 */ setServiceName(String serviceName)230 public Builder setServiceName(String serviceName) { 231 mServiceName = serviceName; 232 return this; 233 } 234 235 /** 236 * Specify service specific information for the subscribe session. This 237 * is a free-form byte array available to the application to send 238 * additional information as part of the discovery operation - i.e. it 239 * will not be used to determine whether a publish/subscribe match 240 * occurs. 241 * 242 * @param serviceSpecificInfo A byte-array for the service-specific 243 * information field. 244 * @param serviceSpecificInfoLength The length of the byte-array to be 245 * used. 246 * @return The builder to facilitate chaining 247 * {@code builder.setXXX(..).setXXX(..)}. 248 */ setServiceSpecificInfo(byte[] serviceSpecificInfo, int serviceSpecificInfoLength)249 public Builder setServiceSpecificInfo(byte[] serviceSpecificInfo, 250 int serviceSpecificInfoLength) { 251 mServiceSpecificInfoLength = serviceSpecificInfoLength; 252 mServiceSpecificInfo = serviceSpecificInfo; 253 return this; 254 } 255 256 /** 257 * Specify service specific information for the subscribe session - same 258 * as {@link SubscribeData.Builder#setServiceSpecificInfo(byte[], int)} 259 * but obtaining the data from a String. 260 * 261 * @param serviceSpecificInfoStr The service specific information string 262 * to be included (as a byte array) in the subscribe 263 * information. 264 * @return The builder to facilitate chaining 265 * {@code builder.setXXX(..).setXXX(..)}. 266 */ setServiceSpecificInfo(String serviceSpecificInfoStr)267 public Builder setServiceSpecificInfo(String serviceSpecificInfoStr) { 268 mServiceSpecificInfoLength = serviceSpecificInfoStr.length(); 269 mServiceSpecificInfo = serviceSpecificInfoStr.getBytes(); 270 return this; 271 } 272 273 /** 274 * The transmit filter for an active subscribe session 275 * {@link SubscribeSettings.Builder#setSubscribeType(int)} and 276 * {@link SubscribeSettings#SUBSCRIBE_TYPE_ACTIVE}. Included in 277 * transmitted subscribe packets and used by receivers (passive 278 * publishers) to determine whether they match - in addition to just 279 * relying on the service name. 280 * <p> 281 * Format is an LV byte array - the {@link TlvBufferUtils} utility class 282 * is available to form and parse. 283 * 284 * @param txFilter The byte-array containing the LV formatted transmit 285 * filter. 286 * @param txFilterLength The number of bytes in the transmit filter 287 * argument. 288 * @return The builder to facilitate chaining 289 * {@code builder.setXXX(..).setXXX(..)}. 290 */ setTxFilter(byte[] txFilter, int txFilterLength)291 public Builder setTxFilter(byte[] txFilter, int txFilterLength) { 292 mTxFilter = txFilter; 293 mTxFilterLength = txFilterLength; 294 return this; 295 } 296 297 /** 298 * The transmit filter for a passive subsribe session 299 * {@link SubscribeSettings.Builder#setSubscribeType(int)} and 300 * {@link SubscribeSettings#SUBSCRIBE_TYPE_PASSIVE}. Used by the 301 * subscriber to determine whether they match transmitted publish 302 * packets - in addition to just relying on the service name. 303 * <p> 304 * Format is an LV byte array - the {@link TlvBufferUtils} utility class 305 * is available to form and parse. 306 * 307 * @param rxFilter The byte-array containing the LV formatted receive 308 * filter. 309 * @param rxFilterLength The number of bytes in the receive filter 310 * argument. 311 * @return The builder to facilitate chaining 312 * {@code builder.setXXX(..).setXXX(..)}. 313 */ setRxFilter(byte[] rxFilter, int rxFilterLength)314 public Builder setRxFilter(byte[] rxFilter, int rxFilterLength) { 315 mRxFilter = rxFilter; 316 mRxFilterLength = rxFilterLength; 317 return this; 318 } 319 320 /** 321 * Build {@link SubscribeData} given the current requests made on the 322 * builder. 323 */ build()324 public SubscribeData build() { 325 return new SubscribeData(mServiceName, mServiceSpecificInfo, mServiceSpecificInfoLength, 326 mTxFilter, mTxFilterLength, mRxFilter, mRxFilterLength); 327 } 328 } 329 } 330