1 /* 2 * Copyright (C) 2021 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 com.android.server.connectivity.mdns; 17 18 import android.annotation.NonNull; 19 import android.annotation.Nullable; 20 21 /** 22 * The class that contains mDNS feature flags; 23 */ 24 public class MdnsFeatureFlags { 25 /** 26 * A feature flag to control whether the mDNS offload is enabled or not. 27 */ 28 public static final String NSD_FORCE_DISABLE_MDNS_OFFLOAD = "nsd_force_disable_mdns_offload"; 29 30 /** 31 * A feature flag to control whether the probing question should include 32 * InetAddressRecords or not. 33 */ 34 public static final String INCLUDE_INET_ADDRESS_RECORDS_IN_PROBING = 35 "include_inet_address_records_in_probing"; 36 /** 37 * A feature flag to control whether expired services removal should be enabled. 38 */ 39 public static final String NSD_EXPIRED_SERVICES_REMOVAL = 40 "nsd_expired_services_removal"; 41 42 /** 43 * A feature flag to control whether the label count limit should be enabled. 44 */ 45 public static final String NSD_LIMIT_LABEL_COUNT = "nsd_limit_label_count"; 46 47 /** 48 * A feature flag to control whether the known-answer suppression should be enabled. 49 */ 50 public static final String NSD_KNOWN_ANSWER_SUPPRESSION = "nsd_known_answer_suppression"; 51 52 /** 53 * A feature flag to control whether unicast replies should be enabled. 54 * 55 * <p>Enabling this feature causes replies to queries with the Query Unicast (QU) flag set to be 56 * sent unicast instead of multicast, as per RFC6762 5.4. 57 */ 58 public static final String NSD_UNICAST_REPLY_ENABLED = "nsd_unicast_reply_enabled"; 59 60 /** 61 * A feature flag to control whether the aggressive query mode should be enabled. 62 */ 63 public static final String NSD_AGGRESSIVE_QUERY_MODE = "nsd_aggressive_query_mode"; 64 65 /** 66 * A feature flag to control whether the query with known-answer should be enabled. 67 */ 68 public static final String NSD_QUERY_WITH_KNOWN_ANSWER = "nsd_query_with_known_answer"; 69 70 /** 71 * A feature flag to avoid advertising empty TXT records, as per RFC 6763 6.1. 72 */ 73 public static final String NSD_AVOID_ADVERTISING_EMPTY_TXT_RECORDS = 74 "nsd_avoid_advertising_empty_txt_records"; 75 76 /** 77 * A feature flag to control whether the cached services removal should be enabled. 78 * The removal will be triggered if the retention time has elapsed after all listeners have been 79 * unregistered from the service type client or the interface has been destroyed. 80 */ 81 public static final String NSD_CACHED_SERVICES_REMOVAL = "nsd_cached_services_removal"; 82 83 /** 84 * A feature flag to control whether to use shorter (16 characters + .local) hostnames, instead 85 * of Android_[32 characters] hostnames. 86 */ 87 public static final String NSD_USE_SHORT_HOSTNAMES = "nsd_use_short_hostnames"; 88 89 /** 90 * A feature flag to control the retention time for cached services. 91 * 92 * <p> Making the retention time configurable allows for testing and future adjustments. 93 */ 94 public static final String NSD_CACHED_SERVICES_RETENTION_TIME = 95 "nsd_cached_services_retention_time"; 96 public static final int DEFAULT_CACHED_SERVICES_RETENTION_TIME_MILLISECONDS = 10000; 97 98 /** 99 * A feature flag to control whether the accurate delay callback should be enabled. 100 */ 101 public static final String NSD_ACCURATE_DELAY_CALLBACK = "nsd_accurate_delay_callback"; 102 103 // Flag for offload feature 104 public final boolean mIsMdnsOffloadFeatureEnabled; 105 106 // Flag for including InetAddressRecords in probing questions. 107 public final boolean mIncludeInetAddressRecordsInProbing; 108 109 // Flag for expired services removal 110 public final boolean mIsExpiredServicesRemovalEnabled; 111 112 // Flag for label count limit 113 public final boolean mIsLabelCountLimitEnabled; 114 115 // Flag for known-answer suppression 116 public final boolean mIsKnownAnswerSuppressionEnabled; 117 118 // Flag to enable replying unicast to queries requesting unicast replies 119 public final boolean mIsUnicastReplyEnabled; 120 121 // Flag for aggressive query mode 122 public final boolean mIsAggressiveQueryModeEnabled; 123 124 // Flag for query with known-answer 125 public final boolean mIsQueryWithKnownAnswerEnabled; 126 127 // Flag for avoiding advertising empty TXT records 128 public final boolean mAvoidAdvertisingEmptyTxtRecords; 129 130 // Flag for cached services removal 131 public final boolean mIsCachedServicesRemovalEnabled; 132 133 // Retention Time for cached services 134 public final long mCachedServicesRetentionTime; 135 136 // Flag for accurate delay callback 137 public final boolean mIsAccurateDelayCallbackEnabled; 138 139 // Flag to use shorter (16 characters + .local) hostnames 140 public final boolean mIsShortHostnamesEnabled; 141 142 @Nullable 143 private final FlagOverrideProvider mOverrideProvider; 144 145 /** 146 * A provider that can indicate whether a flag should be force-enabled for testing purposes. 147 */ 148 public interface FlagOverrideProvider { 149 /** 150 * Indicates whether the flag should be force-enabled for testing purposes. 151 */ isForceEnabledForTest(@onNull String flag)152 boolean isForceEnabledForTest(@NonNull String flag); 153 154 155 /** 156 * Get the int value of the flag for testing purposes. 157 */ getIntValueForTest(@onNull String flag, int defaultValue)158 int getIntValueForTest(@NonNull String flag, int defaultValue); 159 } 160 161 /** 162 * Indicates whether the flag should be force-enabled for testing purposes. 163 */ isForceEnabledForTest(@onNull String flag)164 private boolean isForceEnabledForTest(@NonNull String flag) { 165 return mOverrideProvider != null && mOverrideProvider.isForceEnabledForTest(flag); 166 } 167 168 /** 169 * Get the int value of the flag for testing purposes. 170 * 171 * @return the test int value, or given default value if it is unset or the OverrideProvider 172 * doesn't exist. 173 */ getIntValueForTest(@onNull String flag, int defaultValue)174 private int getIntValueForTest(@NonNull String flag, int defaultValue) { 175 if (mOverrideProvider == null) { 176 return defaultValue; 177 } 178 return mOverrideProvider.getIntValueForTest(flag, defaultValue); 179 } 180 181 /** 182 * Indicates whether {@link #NSD_UNICAST_REPLY_ENABLED} is enabled, including for testing. 183 */ isUnicastReplyEnabled()184 public boolean isUnicastReplyEnabled() { 185 return mIsUnicastReplyEnabled || isForceEnabledForTest(NSD_UNICAST_REPLY_ENABLED); 186 } 187 188 /** 189 * Indicates whether {@link #NSD_AGGRESSIVE_QUERY_MODE} is enabled, including for testing. 190 */ isAggressiveQueryModeEnabled()191 public boolean isAggressiveQueryModeEnabled() { 192 return mIsAggressiveQueryModeEnabled || isForceEnabledForTest(NSD_AGGRESSIVE_QUERY_MODE); 193 } 194 195 /** 196 * Indicates whether {@link #NSD_KNOWN_ANSWER_SUPPRESSION} is enabled, including for testing. 197 */ isKnownAnswerSuppressionEnabled()198 public boolean isKnownAnswerSuppressionEnabled() { 199 return mIsKnownAnswerSuppressionEnabled 200 || isForceEnabledForTest(NSD_KNOWN_ANSWER_SUPPRESSION); 201 } 202 203 /** 204 * Indicates whether {@link #NSD_QUERY_WITH_KNOWN_ANSWER} is enabled, including for testing. 205 */ isQueryWithKnownAnswerEnabled()206 public boolean isQueryWithKnownAnswerEnabled() { 207 return mIsQueryWithKnownAnswerEnabled 208 || isForceEnabledForTest(NSD_QUERY_WITH_KNOWN_ANSWER); 209 } 210 211 /** 212 * Indicates whether {@link #NSD_AVOID_ADVERTISING_EMPTY_TXT_RECORDS} is enabled, including for 213 * testing. 214 */ avoidAdvertisingEmptyTxtRecords()215 public boolean avoidAdvertisingEmptyTxtRecords() { 216 return mAvoidAdvertisingEmptyTxtRecords 217 || isForceEnabledForTest(NSD_AVOID_ADVERTISING_EMPTY_TXT_RECORDS); 218 } 219 220 /** 221 * Indicates whether {@link #NSD_CACHED_SERVICES_REMOVAL} is enabled, including for testing. 222 */ isCachedServicesRemovalEnabled()223 public boolean isCachedServicesRemovalEnabled() { 224 return mIsCachedServicesRemovalEnabled 225 || isForceEnabledForTest(NSD_CACHED_SERVICES_REMOVAL); 226 } 227 228 /** 229 * Get the value which is set to {@link #NSD_CACHED_SERVICES_RETENTION_TIME}, including for 230 * testing. 231 */ getCachedServicesRetentionTime()232 public long getCachedServicesRetentionTime() { 233 return getIntValueForTest( 234 NSD_CACHED_SERVICES_RETENTION_TIME, (int) mCachedServicesRetentionTime); 235 } 236 isShortHostnamesEnabled()237 public boolean isShortHostnamesEnabled() { 238 return mIsShortHostnamesEnabled || isForceEnabledForTest(NSD_USE_SHORT_HOSTNAMES); 239 } 240 241 /** 242 * Indicates whether {@link #NSD_ACCURATE_DELAY_CALLBACK} is enabled, including for testing. 243 */ isAccurateDelayCallbackEnabled()244 public boolean isAccurateDelayCallbackEnabled() { 245 return mIsAccurateDelayCallbackEnabled 246 || isForceEnabledForTest(NSD_ACCURATE_DELAY_CALLBACK); 247 } 248 249 /** 250 * The constructor for {@link MdnsFeatureFlags}. 251 */ MdnsFeatureFlags(boolean isOffloadFeatureEnabled, boolean includeInetAddressRecordsInProbing, boolean isExpiredServicesRemovalEnabled, boolean isLabelCountLimitEnabled, boolean isKnownAnswerSuppressionEnabled, boolean isUnicastReplyEnabled, boolean isAggressiveQueryModeEnabled, boolean isQueryWithKnownAnswerEnabled, boolean avoidAdvertisingEmptyTxtRecords, boolean isCachedServicesRemovalEnabled, long cachedServicesRetentionTime, boolean isAccurateDelayCallbackEnabled, boolean isShortHostnamesEnabled, @Nullable FlagOverrideProvider overrideProvider)252 public MdnsFeatureFlags(boolean isOffloadFeatureEnabled, 253 boolean includeInetAddressRecordsInProbing, 254 boolean isExpiredServicesRemovalEnabled, 255 boolean isLabelCountLimitEnabled, 256 boolean isKnownAnswerSuppressionEnabled, 257 boolean isUnicastReplyEnabled, 258 boolean isAggressiveQueryModeEnabled, 259 boolean isQueryWithKnownAnswerEnabled, 260 boolean avoidAdvertisingEmptyTxtRecords, 261 boolean isCachedServicesRemovalEnabled, 262 long cachedServicesRetentionTime, 263 boolean isAccurateDelayCallbackEnabled, 264 boolean isShortHostnamesEnabled, 265 @Nullable FlagOverrideProvider overrideProvider) { 266 mIsMdnsOffloadFeatureEnabled = isOffloadFeatureEnabled; 267 mIncludeInetAddressRecordsInProbing = includeInetAddressRecordsInProbing; 268 mIsExpiredServicesRemovalEnabled = isExpiredServicesRemovalEnabled; 269 mIsLabelCountLimitEnabled = isLabelCountLimitEnabled; 270 mIsKnownAnswerSuppressionEnabled = isKnownAnswerSuppressionEnabled; 271 mIsUnicastReplyEnabled = isUnicastReplyEnabled; 272 mIsAggressiveQueryModeEnabled = isAggressiveQueryModeEnabled; 273 mIsQueryWithKnownAnswerEnabled = isQueryWithKnownAnswerEnabled; 274 mAvoidAdvertisingEmptyTxtRecords = avoidAdvertisingEmptyTxtRecords; 275 mIsCachedServicesRemovalEnabled = isCachedServicesRemovalEnabled; 276 mCachedServicesRetentionTime = cachedServicesRetentionTime; 277 mIsAccurateDelayCallbackEnabled = isAccurateDelayCallbackEnabled; 278 mIsShortHostnamesEnabled = isShortHostnamesEnabled; 279 mOverrideProvider = overrideProvider; 280 } 281 282 283 /** Returns a {@link Builder} for {@link MdnsFeatureFlags}. */ newBuilder()284 public static Builder newBuilder() { 285 return new Builder(); 286 } 287 288 /** A builder to create {@link MdnsFeatureFlags}. */ 289 public static final class Builder { 290 291 private boolean mIsMdnsOffloadFeatureEnabled; 292 private boolean mIncludeInetAddressRecordsInProbing; 293 private boolean mIsExpiredServicesRemovalEnabled; 294 private boolean mIsLabelCountLimitEnabled; 295 private boolean mIsKnownAnswerSuppressionEnabled; 296 private boolean mIsUnicastReplyEnabled; 297 private boolean mIsAggressiveQueryModeEnabled; 298 private boolean mIsQueryWithKnownAnswerEnabled; 299 private boolean mAvoidAdvertisingEmptyTxtRecords; 300 private boolean mIsCachedServicesRemovalEnabled; 301 private long mCachedServicesRetentionTime; 302 private boolean mIsAccurateDelayCallbackEnabled; 303 private boolean mIsShortHostnamesEnabled; 304 private FlagOverrideProvider mOverrideProvider; 305 306 /** 307 * The constructor for {@link Builder}. 308 */ Builder()309 public Builder() { 310 mIsMdnsOffloadFeatureEnabled = false; 311 mIncludeInetAddressRecordsInProbing = false; 312 mIsExpiredServicesRemovalEnabled = true; // Default enabled. 313 mIsLabelCountLimitEnabled = true; // Default enabled. 314 mIsKnownAnswerSuppressionEnabled = true; // Default enabled. 315 mIsUnicastReplyEnabled = true; // Default enabled. 316 mIsAggressiveQueryModeEnabled = false; 317 mIsQueryWithKnownAnswerEnabled = false; 318 mAvoidAdvertisingEmptyTxtRecords = true; // Default enabled. 319 mIsCachedServicesRemovalEnabled = true; // Default enabled. 320 mCachedServicesRetentionTime = DEFAULT_CACHED_SERVICES_RETENTION_TIME_MILLISECONDS; 321 mIsAccurateDelayCallbackEnabled = false; 322 mIsShortHostnamesEnabled = true; // Default enabled. 323 mOverrideProvider = null; 324 } 325 326 /** 327 * Set whether the mDNS offload feature is enabled. 328 * 329 * @see #NSD_FORCE_DISABLE_MDNS_OFFLOAD 330 */ setIsMdnsOffloadFeatureEnabled(boolean isMdnsOffloadFeatureEnabled)331 public Builder setIsMdnsOffloadFeatureEnabled(boolean isMdnsOffloadFeatureEnabled) { 332 mIsMdnsOffloadFeatureEnabled = isMdnsOffloadFeatureEnabled; 333 return this; 334 } 335 336 /** 337 * Set whether the probing question should include InetAddressRecords. 338 * 339 * @see #INCLUDE_INET_ADDRESS_RECORDS_IN_PROBING 340 */ setIncludeInetAddressRecordsInProbing( boolean includeInetAddressRecordsInProbing)341 public Builder setIncludeInetAddressRecordsInProbing( 342 boolean includeInetAddressRecordsInProbing) { 343 mIncludeInetAddressRecordsInProbing = includeInetAddressRecordsInProbing; 344 return this; 345 } 346 347 /** 348 * Set whether the expired services removal is enabled. 349 * 350 * @see #NSD_EXPIRED_SERVICES_REMOVAL 351 */ setIsExpiredServicesRemovalEnabled(boolean isExpiredServicesRemovalEnabled)352 public Builder setIsExpiredServicesRemovalEnabled(boolean isExpiredServicesRemovalEnabled) { 353 mIsExpiredServicesRemovalEnabled = isExpiredServicesRemovalEnabled; 354 return this; 355 } 356 357 /** 358 * Set whether the label count limit is enabled. 359 * 360 * @see #NSD_LIMIT_LABEL_COUNT 361 */ setIsLabelCountLimitEnabled(boolean isLabelCountLimitEnabled)362 public Builder setIsLabelCountLimitEnabled(boolean isLabelCountLimitEnabled) { 363 mIsLabelCountLimitEnabled = isLabelCountLimitEnabled; 364 return this; 365 } 366 367 /** 368 * Set whether the known-answer suppression is enabled. 369 * 370 * @see #NSD_KNOWN_ANSWER_SUPPRESSION 371 */ setIsKnownAnswerSuppressionEnabled(boolean isKnownAnswerSuppressionEnabled)372 public Builder setIsKnownAnswerSuppressionEnabled(boolean isKnownAnswerSuppressionEnabled) { 373 mIsKnownAnswerSuppressionEnabled = isKnownAnswerSuppressionEnabled; 374 return this; 375 } 376 377 /** 378 * Set whether the unicast reply feature is enabled. 379 * 380 * @see #NSD_UNICAST_REPLY_ENABLED 381 */ setIsUnicastReplyEnabled(boolean isUnicastReplyEnabled)382 public Builder setIsUnicastReplyEnabled(boolean isUnicastReplyEnabled) { 383 mIsUnicastReplyEnabled = isUnicastReplyEnabled; 384 return this; 385 } 386 387 /** 388 * Set a {@link FlagOverrideProvider} to be used by {@link #isForceEnabledForTest(String)}. 389 * 390 * If non-null, features that use {@link #isForceEnabledForTest(String)} will use that 391 * provider to query whether the flag should be force-enabled. 392 */ setOverrideProvider(@ullable FlagOverrideProvider overrideProvider)393 public Builder setOverrideProvider(@Nullable FlagOverrideProvider overrideProvider) { 394 mOverrideProvider = overrideProvider; 395 return this; 396 } 397 398 /** 399 * Set whether the aggressive query mode is enabled. 400 * 401 * @see #NSD_AGGRESSIVE_QUERY_MODE 402 */ setIsAggressiveQueryModeEnabled(boolean isAggressiveQueryModeEnabled)403 public Builder setIsAggressiveQueryModeEnabled(boolean isAggressiveQueryModeEnabled) { 404 mIsAggressiveQueryModeEnabled = isAggressiveQueryModeEnabled; 405 return this; 406 } 407 408 /** 409 * Set whether the query with known-answer is enabled. 410 * 411 * @see #NSD_QUERY_WITH_KNOWN_ANSWER 412 */ setIsQueryWithKnownAnswerEnabled(boolean isQueryWithKnownAnswerEnabled)413 public Builder setIsQueryWithKnownAnswerEnabled(boolean isQueryWithKnownAnswerEnabled) { 414 mIsQueryWithKnownAnswerEnabled = isQueryWithKnownAnswerEnabled; 415 return this; 416 } 417 418 /** 419 * Set whether to avoid advertising empty TXT records. 420 * 421 * @see #NSD_AVOID_ADVERTISING_EMPTY_TXT_RECORDS 422 */ setAvoidAdvertisingEmptyTxtRecords(boolean avoidAdvertisingEmptyTxtRecords)423 public Builder setAvoidAdvertisingEmptyTxtRecords(boolean avoidAdvertisingEmptyTxtRecords) { 424 mAvoidAdvertisingEmptyTxtRecords = avoidAdvertisingEmptyTxtRecords; 425 return this; 426 } 427 428 /** 429 * Set whether the cached services removal is enabled. 430 * 431 * @see #NSD_CACHED_SERVICES_REMOVAL 432 */ setIsCachedServicesRemovalEnabled(boolean isCachedServicesRemovalEnabled)433 public Builder setIsCachedServicesRemovalEnabled(boolean isCachedServicesRemovalEnabled) { 434 mIsCachedServicesRemovalEnabled = isCachedServicesRemovalEnabled; 435 return this; 436 } 437 438 /** 439 * Set cached services retention time. 440 * 441 * @see #NSD_CACHED_SERVICES_RETENTION_TIME 442 */ setCachedServicesRetentionTime(long cachedServicesRetentionTime)443 public Builder setCachedServicesRetentionTime(long cachedServicesRetentionTime) { 444 mCachedServicesRetentionTime = cachedServicesRetentionTime; 445 return this; 446 } 447 448 /** 449 * Set whether the accurate delay callback is enabled. 450 * 451 * @see #NSD_ACCURATE_DELAY_CALLBACK 452 */ setIsAccurateDelayCallbackEnabled(boolean isAccurateDelayCallbackEnabled)453 public Builder setIsAccurateDelayCallbackEnabled(boolean isAccurateDelayCallbackEnabled) { 454 mIsAccurateDelayCallbackEnabled = isAccurateDelayCallbackEnabled; 455 return this; 456 } 457 458 /** 459 * Set whether the short hostnames feature is enabled. 460 * 461 * @see #NSD_USE_SHORT_HOSTNAMES 462 */ setIsShortHostnamesEnabled(boolean isShortHostnamesEnabled)463 public Builder setIsShortHostnamesEnabled(boolean isShortHostnamesEnabled) { 464 mIsShortHostnamesEnabled = isShortHostnamesEnabled; 465 return this; 466 } 467 468 /** 469 * Builds a {@link MdnsFeatureFlags} with the arguments supplied to this builder. 470 */ build()471 public MdnsFeatureFlags build() { 472 return new MdnsFeatureFlags(mIsMdnsOffloadFeatureEnabled, 473 mIncludeInetAddressRecordsInProbing, 474 mIsExpiredServicesRemovalEnabled, 475 mIsLabelCountLimitEnabled, 476 mIsKnownAnswerSuppressionEnabled, 477 mIsUnicastReplyEnabled, 478 mIsAggressiveQueryModeEnabled, 479 mIsQueryWithKnownAnswerEnabled, 480 mAvoidAdvertisingEmptyTxtRecords, 481 mIsCachedServicesRemovalEnabled, 482 mCachedServicesRetentionTime, 483 mIsAccurateDelayCallbackEnabled, 484 mIsShortHostnamesEnabled, 485 mOverrideProvider); 486 } 487 } 488 } 489