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 package android.net.nsd; 17 18 import android.annotation.FlaggedApi; 19 import android.annotation.LongDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.net.nsd.NsdManager.ProtocolType; 23 import android.os.Parcel; 24 import android.os.Parcelable; 25 26 import com.android.net.flags.Flags; 27 28 import java.lang.annotation.Retention; 29 import java.lang.annotation.RetentionPolicy; 30 import java.time.Duration; 31 import java.util.Objects; 32 33 /** 34 * Encapsulates parameters for {@link NsdManager#registerService}. 35 */ 36 @FlaggedApi(Flags.FLAG_IPV6_OVER_BLE) 37 public final class AdvertisingRequest implements Parcelable { 38 39 /** 40 * Only update the registration without sending exit and re-announcement. 41 * @hide 42 */ 43 public static final long NSD_ADVERTISING_UPDATE_ONLY = 1; 44 45 // TODO: if apps are allowed to set hostnames, the below doc should be updated to mention that 46 // passed in hostnames must also be known unique to use this flag. 47 /** 48 * Skip the probing step when advertising. 49 * 50 * <p>This must only be used when the service name ({@link NsdServiceInfo#getServiceName()} is 51 * known to be unique and cannot possibly be used by any other device on the network. 52 */ 53 public static final long FLAG_SKIP_PROBING = 1 << 1; 54 55 /** @hide */ 56 @Retention(RetentionPolicy.SOURCE) 57 @LongDef(flag = true, prefix = {"FLAG_"}, value = { 58 FLAG_SKIP_PROBING, 59 }) 60 public @interface AdvertisingFlags {} 61 62 @NonNull 63 public static final Creator<AdvertisingRequest> CREATOR = 64 new Creator<>() { 65 @Override 66 public AdvertisingRequest createFromParcel(Parcel in) { 67 final NsdServiceInfo serviceInfo = in.readParcelable( 68 NsdServiceInfo.class.getClassLoader(), NsdServiceInfo.class); 69 final int protocolType = in.readInt(); 70 final long advertiseConfig = in.readLong(); 71 final long ttlSeconds = in.readLong(); 72 final Duration ttl = ttlSeconds < 0 ? null : Duration.ofSeconds(ttlSeconds); 73 return new AdvertisingRequest(serviceInfo, protocolType, advertiseConfig, ttl); 74 } 75 76 @Override 77 public AdvertisingRequest[] newArray(int size) { 78 return new AdvertisingRequest[size]; 79 } 80 }; 81 @NonNull 82 private final NsdServiceInfo mServiceInfo; 83 private final int mProtocolType; 84 // Bitmask of @AdvertisingConfig flags. Uses a long to allow 64 possible flags in the future. 85 private final long mAdvertisingConfig; 86 87 @Nullable 88 private final Duration mTtl; 89 90 /** 91 * @hide 92 */ 93 @Retention(RetentionPolicy.SOURCE) 94 @LongDef(flag = true, prefix = {"NSD_ADVERTISING"}, value = { 95 NSD_ADVERTISING_UPDATE_ONLY, 96 }) 97 @interface AdvertisingConfig {} 98 99 /** 100 * The constructor for the advertiseRequest 101 */ AdvertisingRequest(@onNull NsdServiceInfo serviceInfo, @ProtocolType int protocolType, long advertisingConfig, @NonNull Duration ttl)102 private AdvertisingRequest(@NonNull NsdServiceInfo serviceInfo, @ProtocolType int protocolType, 103 long advertisingConfig, @NonNull Duration ttl) { 104 mServiceInfo = serviceInfo; 105 mProtocolType = protocolType; 106 mAdvertisingConfig = advertisingConfig; 107 mTtl = ttl; 108 } 109 110 /** 111 * @return the {@link NsdServiceInfo} describing the service to advertise. 112 */ 113 @NonNull getServiceInfo()114 public NsdServiceInfo getServiceInfo() { 115 return mServiceInfo; 116 } 117 118 /** 119 * @return the service advertisement protocol. 120 */ 121 @ProtocolType getProtocolType()122 public int getProtocolType() { 123 return mProtocolType; 124 } 125 126 /** 127 * @return the flags affecting advertising behavior. 128 */ 129 @AdvertisingFlags getFlags()130 public long getFlags() { 131 return mAdvertisingConfig; 132 } 133 134 /** 135 * Returns the time interval that the resource records may be cached on a DNS resolver. 136 * 137 * The value will be {@code null} if it's not specified with the {@link #Builder}. 138 * 139 * @hide 140 */ 141 // @FlaggedApi(NsdManager.Flags.NSD_CUSTOM_TTL_ENABLED) 142 @Nullable getTtl()143 public Duration getTtl() { 144 return mTtl; 145 } 146 147 @Override toString()148 public String toString() { 149 StringBuilder sb = new StringBuilder(); 150 sb.append("serviceInfo: ").append(mServiceInfo) 151 .append(", protocolType: ").append(mProtocolType) 152 .append(", advertisingConfig: ").append(mAdvertisingConfig) 153 .append(", ttl: ").append(mTtl); 154 return sb.toString(); 155 } 156 157 @Override equals(Object other)158 public boolean equals(Object other) { 159 if (this == other) { 160 return true; 161 } else if (!(other instanceof AdvertisingRequest)) { 162 return false; 163 } else { 164 final AdvertisingRequest otherRequest = (AdvertisingRequest) other; 165 return mServiceInfo.equals(otherRequest.mServiceInfo) 166 && mProtocolType == otherRequest.mProtocolType 167 && mAdvertisingConfig == otherRequest.mAdvertisingConfig 168 && Objects.equals(mTtl, otherRequest.mTtl); 169 } 170 } 171 172 @Override hashCode()173 public int hashCode() { 174 return Objects.hash(mServiceInfo, mProtocolType, mAdvertisingConfig, mTtl); 175 } 176 177 @Override describeContents()178 public int describeContents() { 179 return 0; 180 } 181 182 @Override writeToParcel(@onNull Parcel dest, int flags)183 public void writeToParcel(@NonNull Parcel dest, int flags) { 184 dest.writeParcelable(mServiceInfo, flags); 185 dest.writeInt(mProtocolType); 186 dest.writeLong(mAdvertisingConfig); 187 dest.writeLong(mTtl == null ? -1L : mTtl.getSeconds()); 188 } 189 190 /** 191 * A builder for creating new {@link AdvertisingRequest} objects. 192 */ 193 @FlaggedApi(Flags.FLAG_IPV6_OVER_BLE) 194 public static final class Builder { 195 @NonNull 196 private final NsdServiceInfo mServiceInfo; 197 private int mProtocolType; 198 private long mAdvertisingConfig; 199 @Nullable 200 private Duration mTtl; 201 202 /** 203 * Creates a new {@link Builder} object. 204 * @param serviceInfo the {@link NsdServiceInfo} describing the service to advertise. 205 * @param protocolType the advertising protocol to use. 206 * @hide 207 */ Builder(@onNull NsdServiceInfo serviceInfo, @ProtocolType int protocolType)208 public Builder(@NonNull NsdServiceInfo serviceInfo, @ProtocolType int protocolType) { 209 mServiceInfo = serviceInfo; 210 mProtocolType = protocolType; 211 } 212 213 /** 214 * Creates a new {@link Builder} object. 215 * @param serviceInfo the {@link NsdServiceInfo} describing the service to advertise. 216 */ Builder(@onNull NsdServiceInfo serviceInfo)217 public Builder(@NonNull NsdServiceInfo serviceInfo) { 218 this(serviceInfo, NsdManager.PROTOCOL_DNS_SD); 219 } 220 221 /** 222 * Sets advertising configuration flags. 223 * 224 * @param flags flags to use for advertising. 225 */ 226 @NonNull setFlags(@dvertisingFlags long flags)227 public Builder setFlags(@AdvertisingFlags long flags) { 228 mAdvertisingConfig = flags; 229 return this; 230 } 231 232 /** 233 * Sets the time interval that the resource records may be cached on a DNS resolver. 234 * 235 * If this method is not called or {@code ttl} is {@code null}, default TTL values 236 * will be used for the service when it's registered. Otherwise, the {@code ttl} 237 * will be used for all resource records of this service. 238 * 239 * When registering a service, {@link NsdManager#FAILURE_BAD_PARAMETERS} will be returned 240 * if {@code ttl} is smaller than 30 seconds. 241 * 242 * Note: the value after the decimal point (in unit of seconds) will be discarded. For 243 * example, {@code 30} seconds will be used when {@code Duration.ofSeconds(30L, 50_000L)} 244 * is provided. 245 * 246 * @param ttl the maximum duration that the DNS resource records will be cached 247 * 248 * @see AdvertisingRequest#getTtl 249 * @hide 250 */ 251 // @FlaggedApi(NsdManager.Flags.NSD_CUSTOM_TTL_ENABLED) 252 @NonNull setTtl(@ullable Duration ttl)253 public Builder setTtl(@Nullable Duration ttl) { 254 if (ttl == null) { 255 mTtl = null; 256 return this; 257 } 258 final long ttlSeconds = ttl.getSeconds(); 259 if (ttlSeconds < 0 || ttlSeconds > 0xffffffffL) { 260 throw new IllegalArgumentException( 261 "ttlSeconds exceeds the allowed range (value = " + ttlSeconds 262 + ", allowedRanged = [0, 0xffffffffL])"); 263 } 264 mTtl = Duration.ofSeconds(ttlSeconds); 265 return this; 266 } 267 268 /** 269 * Sets the protocol to use for advertising. 270 * @param protocolType the advertising protocol to use. 271 */ 272 @NonNull setProtocolType(@rotocolType int protocolType)273 public Builder setProtocolType(@ProtocolType int protocolType) { 274 mProtocolType = protocolType; 275 return this; 276 } 277 278 /** Creates a new {@link AdvertisingRequest} object. */ 279 @NonNull build()280 public AdvertisingRequest build() { 281 return new AdvertisingRequest(mServiceInfo, mProtocolType, mAdvertisingConfig, mTtl); 282 } 283 } 284 } 285