diff --git a/core/src/main/java/io/grpc/internal/DnsNameResolver.java b/core/src/main/java/io/grpc/internal/DnsNameResolver.java
index 1f060b3014..fbd5762afe 100644
--- a/core/src/main/java/io/grpc/internal/DnsNameResolver.java
+++ b/core/src/main/java/io/grpc/internal/DnsNameResolver.java
@@ -98,6 +98,8 @@ final class DnsNameResolver extends NameResolver {
*
Default value is -1 (cache forever) if security manager is installed. If security manager is
* not installed, the ttl value is {@code null} which falls back to {@link
* #DEFAULT_NETWORK_CACHE_TTL_SECONDS gRPC default value}.
+ *
+ *
For android, gRPC doesn't attempt to cache; this property value will be ignored.
*/
@VisibleForTesting
static final String NETWORKADDRESS_CACHE_TTL_PROPERTY = "networkaddress.cache.ttl";
@@ -143,7 +145,7 @@ final class DnsNameResolver extends NameResolver {
DnsNameResolver(@Nullable String nsAuthority, String name, Attributes params,
Resource executorResource, ProxyDetector proxyDetector,
- Stopwatch stopwatch) {
+ Stopwatch stopwatch, boolean isAndroid) {
// TODO: if a DNS server is provided as nsAuthority, use it.
// https://www.captechconsulting.com/blogs/accessing-the-dusty-corners-of-dns-with-java
this.executorResource = executorResource;
@@ -166,7 +168,7 @@ final class DnsNameResolver extends NameResolver {
port = nameUri.getPort();
}
this.proxyDetector = proxyDetector;
- this.resolveRunnable = new Resolve(this, stopwatch);
+ this.resolveRunnable = new Resolve(this, stopwatch, getNetworkAddressCacheTtlNanos(isAndroid));
}
@Override
@@ -196,10 +198,10 @@ final class DnsNameResolver extends NameResolver {
private final long cacheTtlNanos;
private ResolutionResults cachedResolutionResults = null;
- Resolve(DnsNameResolver resolver, Stopwatch stopwatch) {
+ Resolve(DnsNameResolver resolver, Stopwatch stopwatch, long cacheTtlNanos) {
this.resolver = resolver;
this.stopwatch = Preconditions.checkNotNull(stopwatch, "stopwatch");
- this.cacheTtlNanos = getNetworkAddressCacheTtlNanos();
+ this.cacheTtlNanos = cacheTtlNanos;
}
@Override
@@ -230,23 +232,6 @@ final class DnsNameResolver extends NameResolver {
|| (cacheTtlNanos > 0 && stopwatch.elapsed(TimeUnit.NANOSECONDS) > cacheTtlNanos);
}
- /** Returns value of network address cache ttl property. */
- private static long getNetworkAddressCacheTtlNanos() {
- String cacheTtlPropertyValue = System.getProperty(NETWORKADDRESS_CACHE_TTL_PROPERTY);
- long cacheTtl = DEFAULT_NETWORK_CACHE_TTL_SECONDS;
- if (cacheTtlPropertyValue != null) {
- try {
- cacheTtl = Long.parseLong(cacheTtlPropertyValue);
- } catch (NumberFormatException e) {
- logger.log(
- Level.WARNING,
- "Property({0}) valid is not valid number format({1}), fall back to default({2})",
- new Object[] {NETWORKADDRESS_CACHE_TTL_PROPERTY, cacheTtlPropertyValue, cacheTtl});
- }
- }
- return cacheTtl > 0 ? TimeUnit.SECONDS.toNanos(cacheTtl) : cacheTtl;
- }
-
@VisibleForTesting
void resolveInternal(Listener savedListener) {
InetSocketAddress destination =
@@ -483,6 +468,31 @@ final class DnsNameResolver extends NameResolver {
ServiceConfigUtil.getList(serviceConfigChoice, SERVICE_CONFIG_CHOICE_CLIENT_HOSTNAME_KEY));
}
+ /**
+ * Returns value of network address cache ttl property if not Android environment. For android,
+ * DnsNameResolver does not cache the dns lookup result.
+ */
+ private static long getNetworkAddressCacheTtlNanos(boolean isAndroid) {
+ if (isAndroid) {
+ // on Android, ignore dns cache.
+ return 0;
+ }
+
+ String cacheTtlPropertyValue = System.getProperty(NETWORKADDRESS_CACHE_TTL_PROPERTY);
+ long cacheTtl = DEFAULT_NETWORK_CACHE_TTL_SECONDS;
+ if (cacheTtlPropertyValue != null) {
+ try {
+ cacheTtl = Long.parseLong(cacheTtlPropertyValue);
+ } catch (NumberFormatException e) {
+ logger.log(
+ Level.WARNING,
+ "Property({0}) valid is not valid number format({1}), fall back to default({2})",
+ new Object[] {NETWORKADDRESS_CACHE_TTL_PROPERTY, cacheTtlPropertyValue, cacheTtl});
+ }
+ }
+ return cacheTtl > 0 ? TimeUnit.SECONDS.toNanos(cacheTtl) : cacheTtl;
+ }
+
/**
* Determines if a given Service Config choice applies, and if so, returns it.
*
diff --git a/core/src/main/java/io/grpc/internal/DnsNameResolverProvider.java b/core/src/main/java/io/grpc/internal/DnsNameResolverProvider.java
index d0db539d41..eda7754477 100644
--- a/core/src/main/java/io/grpc/internal/DnsNameResolverProvider.java
+++ b/core/src/main/java/io/grpc/internal/DnsNameResolverProvider.java
@@ -19,6 +19,7 @@ package io.grpc.internal;
import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
import io.grpc.Attributes;
+import io.grpc.InternalServiceProviders;
import io.grpc.NameResolverProvider;
import java.net.URI;
@@ -54,7 +55,8 @@ public final class DnsNameResolverProvider extends NameResolverProvider {
params,
GrpcUtil.SHARED_CHANNEL_EXECUTOR,
GrpcUtil.getDefaultProxyDetector(),
- Stopwatch.createUnstarted());
+ Stopwatch.createUnstarted(),
+ InternalServiceProviders.isAndroid(getClass().getClassLoader()));
} else {
return null;
}
diff --git a/core/src/test/java/io/grpc/internal/DnsNameResolverTest.java b/core/src/test/java/io/grpc/internal/DnsNameResolverTest.java
index 5a34520bc0..a3aa7315cd 100644
--- a/core/src/test/java/io/grpc/internal/DnsNameResolverTest.java
+++ b/core/src/test/java/io/grpc/internal/DnsNameResolverTest.java
@@ -118,18 +118,34 @@ public class DnsNameResolverTest {
return newResolver(name, port, GrpcUtil.NOOP_PROXY_DETECTOR, Stopwatch.createUnstarted());
}
+ private DnsNameResolver newResolver(String name, int port, boolean isAndroid) {
+ return
+ newResolver(
+ name, port, GrpcUtil.NOOP_PROXY_DETECTOR, Stopwatch.createUnstarted(), isAndroid);
+ }
+
private DnsNameResolver newResolver(
String name,
int port,
ProxyDetector proxyDetector,
Stopwatch stopwatch) {
+ return newResolver(name, port, proxyDetector, stopwatch, false);
+ }
+
+ private DnsNameResolver newResolver(
+ String name,
+ int port,
+ ProxyDetector proxyDetector,
+ Stopwatch stopwatch,
+ boolean isAndroid) {
DnsNameResolver dnsResolver = new DnsNameResolver(
null,
name,
Attributes.newBuilder().set(NameResolver.Factory.PARAMS_DEFAULT_PORT, port).build(),
fakeExecutorResource,
proxyDetector,
- stopwatch);
+ stopwatch,
+ isAndroid);
return dnsResolver;
}
@@ -200,14 +216,30 @@ public class DnsNameResolverTest {
}
}
+ @Test
+ public void resolve_androidIgnoresPropertyValue() throws Exception {
+ System.setProperty(DnsNameResolver.NETWORKADDRESS_CACHE_TTL_PROPERTY, Long.toString(2));
+ resolveNeverCache(true);
+ }
+
+ @Test
+ public void resolve_androidIgnoresPropertyValueCacheForever() throws Exception {
+ System.setProperty(DnsNameResolver.NETWORKADDRESS_CACHE_TTL_PROPERTY, Long.toString(-1));
+ resolveNeverCache(true);
+ }
+
@Test
public void resolve_neverCache() throws Exception {
System.setProperty(DnsNameResolver.NETWORKADDRESS_CACHE_TTL_PROPERTY, "0");
+ resolveNeverCache(false);
+ }
+
+ private void resolveNeverCache(boolean isAndroid) throws Exception {
final List answer1 = createAddressList(2);
final List answer2 = createAddressList(1);
String name = "foo.googleapis.com";
- DnsNameResolver resolver = newResolver(name, 81);
+ DnsNameResolver resolver = newResolver(name, 81, isAndroid);
AddressResolver mockResolver = mock(AddressResolver.class);
when(mockResolver.resolveAddress(Matchers.anyString())).thenReturn(answer1).thenReturn(answer2);
resolver.setAddressResolver(mockResolver);
@@ -241,7 +273,7 @@ public class DnsNameResolverTest {
}
});
- new DnsNameResolver.Resolve(nrf, Stopwatch.createUnstarted()).resolveInternal(mockListener);
+ new DnsNameResolver.Resolve(nrf, Stopwatch.createUnstarted(), 0).resolveInternal(mockListener);
ArgumentCaptor ac = ArgumentCaptor.forClass(Status.class);
verify(mockListener).onError(ac.capture());