• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018, 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 com.android.server.connectivity;
18 
19 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_DEFAULT_MODE;
20 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE;
21 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF;
22 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
23 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
24 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_SPECIFIER;
25 import static android.net.NetworkCapabilities.MAX_TRANSPORT;
26 import static android.net.NetworkCapabilities.MIN_TRANSPORT;
27 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
28 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
29 import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_FAILURE;
30 import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_SUCCESS;
31 
32 import static com.android.testutils.MiscAsserts.assertFieldCountEquals;
33 
34 import static org.junit.Assert.assertEquals;
35 import static org.junit.Assert.assertFalse;
36 import static org.junit.Assert.assertNotNull;
37 import static org.junit.Assert.assertNull;
38 import static org.junit.Assert.assertTrue;
39 import static org.mockito.Mockito.eq;
40 import static org.mockito.Mockito.reset;
41 import static org.mockito.Mockito.times;
42 import static org.mockito.Mockito.verify;
43 import static org.mockito.Mockito.when;
44 
45 import android.annotation.Nullable;
46 import android.content.Context;
47 import android.net.ConnectivitySettingsManager;
48 import android.net.IDnsResolver;
49 import android.net.IpPrefix;
50 import android.net.LinkAddress;
51 import android.net.LinkProperties;
52 import android.net.Network;
53 import android.net.NetworkCapabilities;
54 import android.net.ResolverOptionsParcel;
55 import android.net.ResolverParamsParcel;
56 import android.net.RouteInfo;
57 import android.net.resolv.aidl.DohParamsParcel;
58 import android.net.shared.PrivateDnsConfig;
59 import android.os.Build;
60 import android.provider.Settings;
61 import android.test.mock.MockContentResolver;
62 import android.util.SparseArray;
63 
64 import androidx.test.filters.SmallTest;
65 
66 import com.android.internal.util.MessageUtils;
67 import com.android.internal.util.test.FakeSettingsProvider;
68 import com.android.testutils.DevSdkIgnoreRule;
69 import com.android.testutils.DevSdkIgnoreRunner;
70 
71 import libcore.net.InetAddressUtils;
72 
73 import org.junit.Before;
74 import org.junit.Test;
75 import org.junit.runner.RunWith;
76 import org.mockito.Mock;
77 import org.mockito.MockitoAnnotations;
78 
79 import java.net.InetAddress;
80 import java.util.Arrays;
81 
82 /**
83  * Tests for {@link DnsManager}.
84  *
85  * Build, install and run with:
86  *  runtest frameworks-net -c com.android.server.connectivity.DnsManagerTest
87  */
88 @RunWith(DevSdkIgnoreRunner.class)
89 @SmallTest
90 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
91 public class DnsManagerTest {
92     static final String TEST_IFACENAME = "test_wlan0";
93     static final int TEST_NETID = 100;
94     static final int TEST_NETID_ALTERNATE = 101;
95     static final int TEST_NETID_UNTRACKED = 102;
96     static final int TEST_DEFAULT_SAMPLE_VALIDITY_SECONDS = 1800;
97     static final int TEST_DEFAULT_SUCCESS_THRESHOLD_PERCENT = 25;
98     static final int TEST_DEFAULT_MIN_SAMPLES = 8;
99     static final int TEST_DEFAULT_MAX_SAMPLES = 64;
100     static final int[] TEST_TRANSPORT_TYPES = {TRANSPORT_WIFI, TRANSPORT_VPN};
101 
102     DnsManager mDnsManager;
103     MockContentResolver mContentResolver;
104 
105     @Mock Context mCtx;
106     @Mock IDnsResolver mMockDnsResolver;
107 
assertResolverOptionsEquals( @ullable ResolverOptionsParcel actual, @Nullable ResolverOptionsParcel expected)108     private void assertResolverOptionsEquals(
109             @Nullable ResolverOptionsParcel actual,
110             @Nullable ResolverOptionsParcel expected) {
111         if (actual == null) {
112             assertNull(expected);
113             return;
114         } else {
115             assertNotNull(expected);
116         }
117         assertEquals(actual.hosts, expected.hosts);
118         assertEquals(actual.tcMode, expected.tcMode);
119         assertEquals(actual.enforceDnsUid, expected.enforceDnsUid);
120         assertFieldCountEquals(3, ResolverOptionsParcel.class);
121     }
122 
123     @Before
setUp()124     public void setUp() throws Exception {
125         MockitoAnnotations.initMocks(this);
126         mContentResolver = new MockContentResolver();
127         mContentResolver.addProvider(Settings.AUTHORITY,
128                 new FakeSettingsProvider());
129         when(mCtx.getContentResolver()).thenReturn(mContentResolver);
130         mDnsManager = new DnsManager(mCtx, mMockDnsResolver);
131 
132         // Clear the private DNS settings
133         Settings.Global.putString(mContentResolver, PRIVATE_DNS_DEFAULT_MODE, "");
134         Settings.Global.putString(mContentResolver, PRIVATE_DNS_MODE, "");
135         Settings.Global.putString(mContentResolver, PRIVATE_DNS_SPECIFIER, "");
136     }
137 
138     @Test
testTrackedValidationUpdates()139     public void testTrackedValidationUpdates() throws Exception {
140         mDnsManager.updatePrivateDns(new Network(TEST_NETID),
141                 mDnsManager.getPrivateDnsConfig());
142         mDnsManager.updatePrivateDns(new Network(TEST_NETID_ALTERNATE),
143                 mDnsManager.getPrivateDnsConfig());
144         LinkProperties lp = new LinkProperties();
145         lp.setInterfaceName(TEST_IFACENAME);
146         lp.addDnsServer(InetAddress.getByName("3.3.3.3"));
147         lp.addDnsServer(InetAddress.getByName("4.4.4.4"));
148 
149         // Send a validation event that is tracked on the alternate netId
150         final NetworkCapabilities nc = new NetworkCapabilities();
151         nc.setTransportTypes(TEST_TRANSPORT_TYPES);
152         mDnsManager.updateCapabilitiesForNetwork(TEST_NETID, nc);
153         mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp);
154         mDnsManager.flushVmDnsCache();
155         mDnsManager.updateCapabilitiesForNetwork(TEST_NETID_ALTERNATE, nc);
156         mDnsManager.noteDnsServersForNetwork(TEST_NETID_ALTERNATE, lp);
157         mDnsManager.flushVmDnsCache();
158         mDnsManager.updatePrivateDnsValidation(
159                 new DnsManager.PrivateDnsValidationUpdate(TEST_NETID_ALTERNATE,
160                         InetAddress.parseNumericAddress("4.4.4.4"), "",
161                         VALIDATION_RESULT_SUCCESS));
162         LinkProperties fixedLp = new LinkProperties(lp);
163         mDnsManager.updatePrivateDnsStatus(TEST_NETID, fixedLp);
164         assertFalse(fixedLp.isPrivateDnsActive());
165         assertNull(fixedLp.getPrivateDnsServerName());
166         fixedLp = new LinkProperties(lp);
167         mDnsManager.updatePrivateDnsStatus(TEST_NETID_ALTERNATE, fixedLp);
168         assertTrue(fixedLp.isPrivateDnsActive());
169         assertNull(fixedLp.getPrivateDnsServerName());
170         assertEquals(Arrays.asList(InetAddress.getByName("4.4.4.4")),
171                 fixedLp.getValidatedPrivateDnsServers());
172 
173         // Set up addresses for strict mode and switch to it.
174         lp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
175         lp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
176                 TEST_IFACENAME));
177         lp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
178         lp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
179                 TEST_IFACENAME));
180 
181         ConnectivitySettingsManager.setPrivateDnsMode(mCtx, PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
182         ConnectivitySettingsManager.setPrivateDnsHostname(mCtx, "strictmode.com");
183         mDnsManager.updatePrivateDns(new Network(TEST_NETID),
184                 new PrivateDnsConfig("strictmode.com", new InetAddress[] {
185                     InetAddress.parseNumericAddress("6.6.6.6"),
186                     InetAddress.parseNumericAddress("2001:db8:66:66::1")
187                     }));
188         mDnsManager.updateCapabilitiesForNetwork(TEST_NETID, nc);
189         mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp);
190         mDnsManager.flushVmDnsCache();
191         fixedLp = new LinkProperties(lp);
192         mDnsManager.updatePrivateDnsStatus(TEST_NETID, fixedLp);
193         assertTrue(fixedLp.isPrivateDnsActive());
194         assertEquals("strictmode.com", fixedLp.getPrivateDnsServerName());
195         // No validation events yet.
196         assertEquals(Arrays.asList(new InetAddress[0]), fixedLp.getValidatedPrivateDnsServers());
197         // Validate one.
198         mDnsManager.updatePrivateDnsValidation(
199                 new DnsManager.PrivateDnsValidationUpdate(TEST_NETID,
200                         InetAddress.parseNumericAddress("6.6.6.6"), "strictmode.com",
201                         VALIDATION_RESULT_SUCCESS));
202         fixedLp = new LinkProperties(lp);
203         mDnsManager.updatePrivateDnsStatus(TEST_NETID, fixedLp);
204         assertEquals(Arrays.asList(InetAddress.parseNumericAddress("6.6.6.6")),
205                 fixedLp.getValidatedPrivateDnsServers());
206         // Validate the 2nd one.
207         mDnsManager.updatePrivateDnsValidation(
208                 new DnsManager.PrivateDnsValidationUpdate(TEST_NETID,
209                         InetAddress.parseNumericAddress("2001:db8:66:66::1"), "strictmode.com",
210                         VALIDATION_RESULT_SUCCESS));
211         fixedLp = new LinkProperties(lp);
212         mDnsManager.updatePrivateDnsStatus(TEST_NETID, fixedLp);
213         assertEquals(Arrays.asList(
214                         InetAddress.parseNumericAddress("2001:db8:66:66::1"),
215                         InetAddress.parseNumericAddress("6.6.6.6")),
216                 fixedLp.getValidatedPrivateDnsServers());
217     }
218 
219     @Test
testIgnoreUntrackedValidationUpdates()220     public void testIgnoreUntrackedValidationUpdates() throws Exception {
221         // The PrivateDnsConfig map is empty, so no validation events will
222         // be tracked.
223         LinkProperties lp = new LinkProperties();
224         lp.addDnsServer(InetAddress.getByName("3.3.3.3"));
225         final NetworkCapabilities nc = new NetworkCapabilities();
226         nc.setTransportTypes(TEST_TRANSPORT_TYPES);
227         mDnsManager.updateCapabilitiesForNetwork(TEST_NETID, nc);
228         mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp);
229         mDnsManager.flushVmDnsCache();
230         mDnsManager.updatePrivateDnsValidation(
231                 new DnsManager.PrivateDnsValidationUpdate(TEST_NETID,
232                         InetAddress.parseNumericAddress("3.3.3.3"), "",
233                         VALIDATION_RESULT_SUCCESS));
234         mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp);
235         assertFalse(lp.isPrivateDnsActive());
236         assertNull(lp.getPrivateDnsServerName());
237 
238         // Validation event has untracked netId
239         mDnsManager.updatePrivateDns(new Network(TEST_NETID),
240                 mDnsManager.getPrivateDnsConfig());
241         mDnsManager.updateCapabilitiesForNetwork(TEST_NETID, nc);
242         mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp);
243         mDnsManager.flushVmDnsCache();
244         mDnsManager.updatePrivateDnsValidation(
245                 new DnsManager.PrivateDnsValidationUpdate(TEST_NETID_UNTRACKED,
246                         InetAddress.parseNumericAddress("3.3.3.3"), "",
247                         VALIDATION_RESULT_SUCCESS));
248         mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp);
249         assertFalse(lp.isPrivateDnsActive());
250         assertNull(lp.getPrivateDnsServerName());
251 
252         // Validation event has untracked ipAddress
253         mDnsManager.updatePrivateDnsValidation(
254                 new DnsManager.PrivateDnsValidationUpdate(TEST_NETID,
255                         InetAddress.parseNumericAddress("4.4.4.4"), "",
256                         VALIDATION_RESULT_SUCCESS));
257         mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp);
258         assertFalse(lp.isPrivateDnsActive());
259         assertNull(lp.getPrivateDnsServerName());
260 
261         // Validation event has untracked hostname
262         mDnsManager.updatePrivateDnsValidation(
263                 new DnsManager.PrivateDnsValidationUpdate(TEST_NETID,
264                         InetAddress.parseNumericAddress("3.3.3.3"), "hostname",
265                         VALIDATION_RESULT_SUCCESS));
266         mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp);
267         assertFalse(lp.isPrivateDnsActive());
268         assertNull(lp.getPrivateDnsServerName());
269 
270         // Validation event failed
271         mDnsManager.updatePrivateDnsValidation(
272                 new DnsManager.PrivateDnsValidationUpdate(TEST_NETID,
273                         InetAddress.parseNumericAddress("3.3.3.3"), "",
274                         VALIDATION_RESULT_FAILURE));
275         mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp);
276         assertFalse(lp.isPrivateDnsActive());
277         assertNull(lp.getPrivateDnsServerName());
278 
279         // Network removed
280         mDnsManager.removeNetwork(new Network(TEST_NETID));
281         mDnsManager.updatePrivateDnsValidation(
282                 new DnsManager.PrivateDnsValidationUpdate(TEST_NETID,
283                         InetAddress.parseNumericAddress("3.3.3.3"), "", VALIDATION_RESULT_SUCCESS));
284         mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp);
285         assertFalse(lp.isPrivateDnsActive());
286         assertNull(lp.getPrivateDnsServerName());
287 
288         // Turn private DNS mode off
289         ConnectivitySettingsManager.setPrivateDnsMode(mCtx, PRIVATE_DNS_MODE_OFF);
290         mDnsManager.updatePrivateDns(new Network(TEST_NETID),
291                 mDnsManager.getPrivateDnsConfig());
292         mDnsManager.updateCapabilitiesForNetwork(TEST_NETID, nc);
293         mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp);
294         mDnsManager.flushVmDnsCache();
295         mDnsManager.updatePrivateDnsValidation(
296                 new DnsManager.PrivateDnsValidationUpdate(TEST_NETID,
297                         InetAddress.parseNumericAddress("3.3.3.3"), "",
298                         VALIDATION_RESULT_SUCCESS));
299         mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp);
300         assertFalse(lp.isPrivateDnsActive());
301         assertNull(lp.getPrivateDnsServerName());
302     }
303 
304     @Test
testOverrideDefaultMode()305     public void testOverrideDefaultMode() throws Exception {
306         // Hard-coded default is opportunistic mode.
307         final PrivateDnsConfig cfgAuto = DnsManager.getPrivateDnsConfig(mCtx);
308         assertEquals(PRIVATE_DNS_MODE_OPPORTUNISTIC, cfgAuto.mode);
309         assertEquals("", cfgAuto.hostname);
310         assertEquals(new InetAddress[0], cfgAuto.ips);
311 
312         // Pretend a gservices push sets the default to "off".
313         ConnectivitySettingsManager.setPrivateDnsDefaultMode(mCtx, PRIVATE_DNS_MODE_OFF);
314         final PrivateDnsConfig cfgOff = DnsManager.getPrivateDnsConfig(mCtx);
315         assertEquals(PRIVATE_DNS_MODE_OFF, cfgOff.mode);
316         assertEquals("", cfgOff.hostname);
317         assertEquals(new InetAddress[0], cfgOff.ips);
318 
319         // Strict mode still works.
320         ConnectivitySettingsManager.setPrivateDnsMode(mCtx, PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
321         ConnectivitySettingsManager.setPrivateDnsHostname(mCtx, "strictmode.com");
322         final PrivateDnsConfig cfgStrict = DnsManager.getPrivateDnsConfig(mCtx);
323         assertEquals(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, cfgStrict.mode);
324         assertEquals("strictmode.com", cfgStrict.hostname);
325         assertEquals(new InetAddress[0], cfgStrict.ips);
326     }
327 
doTestSendDnsConfiguration(PrivateDnsConfig cfg, DohParamsParcel expectedDohParams)328     private void doTestSendDnsConfiguration(PrivateDnsConfig cfg, DohParamsParcel expectedDohParams)
329             throws Exception {
330         reset(mMockDnsResolver);
331         mDnsManager.updatePrivateDns(new Network(TEST_NETID), cfg);
332         final LinkProperties lp = new LinkProperties();
333         lp.setInterfaceName(TEST_IFACENAME);
334         lp.addDnsServer(InetAddress.getByName("3.3.3.3"));
335         lp.addDnsServer(InetAddress.getByName("4.4.4.4"));
336         final NetworkCapabilities nc = new NetworkCapabilities();
337         nc.setTransportTypes(TEST_TRANSPORT_TYPES);
338         mDnsManager.updateCapabilitiesForNetwork(TEST_NETID, nc);
339         mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp);
340         mDnsManager.flushVmDnsCache();
341 
342         final ResolverParamsParcel expectedParams = new ResolverParamsParcel();
343         expectedParams.netId = TEST_NETID;
344         expectedParams.sampleValiditySeconds = TEST_DEFAULT_SAMPLE_VALIDITY_SECONDS;
345         expectedParams.successThreshold = TEST_DEFAULT_SUCCESS_THRESHOLD_PERCENT;
346         expectedParams.minSamples = TEST_DEFAULT_MIN_SAMPLES;
347         expectedParams.maxSamples = TEST_DEFAULT_MAX_SAMPLES;
348         expectedParams.servers = new String[]{"3.3.3.3", "4.4.4.4"};
349         expectedParams.domains = new String[]{};
350         expectedParams.tlsName = "";
351         expectedParams.tlsServers = new String[]{"3.3.3.3", "4.4.4.4"};
352         expectedParams.transportTypes = TEST_TRANSPORT_TYPES;
353         expectedParams.resolverOptions = null;
354         expectedParams.meteredNetwork = true;
355         expectedParams.dohParams = expectedDohParams;
356         expectedParams.interfaceNames = new String[]{TEST_IFACENAME};
357         verify(mMockDnsResolver, times(1)).setResolverConfiguration(eq(expectedParams));
358     }
359 
360     @Test
testSendDnsConfiguration_ddrDisabled()361     public void testSendDnsConfiguration_ddrDisabled() throws Exception {
362         final PrivateDnsConfig cfg = new PrivateDnsConfig(
363                 PRIVATE_DNS_MODE_OPPORTUNISTIC /* mode */,
364                 null /* hostname */,
365                 null /* ips */,
366                 false /* ddrEnabled */,
367                 null /* dohName */,
368                 null /* dohIps */,
369                 null /* dohPath */,
370                 -1 /* dohPort */);
371         doTestSendDnsConfiguration(cfg, null /* expectedDohParams */);
372     }
373 
374     @Test
testSendDnsConfiguration_ddrEnabledEmpty()375     public void testSendDnsConfiguration_ddrEnabledEmpty() throws Exception {
376         final PrivateDnsConfig cfg = new PrivateDnsConfig(
377                 PRIVATE_DNS_MODE_OPPORTUNISTIC /* mode */,
378                 null /* hostname */,
379                 null /* ips */,
380                 true /* ddrEnabled */,
381                 null /* dohName */,
382                 null /* dohIps */,
383                 null /* dohPath */,
384                 -1 /* dohPort */);
385 
386         final DohParamsParcel params = new DohParamsParcel.Builder().build();
387         doTestSendDnsConfiguration(cfg, params);
388     }
389 
390     @Test
testSendDnsConfiguration_ddrEnabled()391     public void testSendDnsConfiguration_ddrEnabled() throws Exception {
392         final PrivateDnsConfig cfg = new PrivateDnsConfig(
393                 PRIVATE_DNS_MODE_OPPORTUNISTIC /* mode */,
394                 null /* hostname */,
395                 null /* ips */,
396                 true /* ddrEnabled */,
397                 "doh.com" /* dohName */,
398                 null /* dohIps */,
399                 "/some-path{?dns}" /* dohPath */,
400                 5353 /* dohPort */);
401 
402         final DohParamsParcel params = new DohParamsParcel.Builder()
403                 .setName("doh.com")
404                 .setDohpath("/some-path{?dns}")
405                 .setPort(5353)
406                 .build();
407 
408         doTestSendDnsConfiguration(cfg, params);
409     }
410 
411     @Test
testTransportTypesEqual()412     public void testTransportTypesEqual() throws Exception {
413         SparseArray<String> ncTransTypes = MessageUtils.findMessageNames(
414                 new Class[] { NetworkCapabilities.class }, new String[]{ "TRANSPORT_" });
415         SparseArray<String> dnsTransTypes = MessageUtils.findMessageNames(
416                 new Class[] { IDnsResolver.class }, new String[]{ "TRANSPORT_" });
417         assertEquals(0, MIN_TRANSPORT);
418         assertEquals(MAX_TRANSPORT + 1, ncTransTypes.size());
419         // TRANSPORT_UNKNOWN in IDnsResolver is defined to -1 and only for resolver.
420         assertEquals("TRANSPORT_UNKNOWN", dnsTransTypes.get(-1));
421         assertEquals(ncTransTypes.size(), dnsTransTypes.size() - 1);
422         for (int i = MIN_TRANSPORT; i < MAX_TRANSPORT; i++) {
423             String name = ncTransTypes.get(i, null);
424             assertNotNull("Could not find NetworkCapabilies.TRANSPORT_* constant equal to "
425                     + i, name);
426             assertEquals(name, dnsTransTypes.get(i));
427         }
428     }
429 
430     @Test
testGetPrivateDnsConfigForNetwork()431     public void testGetPrivateDnsConfigForNetwork() throws Exception {
432         final Network network = new Network(TEST_NETID);
433         final InetAddress dnsAddr = InetAddressUtils.parseNumericAddress("3.3.3.3");
434         final InetAddress[] tlsAddrs = new InetAddress[]{
435             InetAddressUtils.parseNumericAddress("6.6.6.6"),
436             InetAddressUtils.parseNumericAddress("2001:db8:66:66::1")
437         };
438         final String tlsName = "strictmode.com";
439         LinkProperties lp = new LinkProperties();
440         lp.addDnsServer(dnsAddr);
441 
442         // The PrivateDnsConfig map is empty, so the default PRIVATE_DNS_OFF is returned.
443         PrivateDnsConfig privateDnsCfg = mDnsManager.getPrivateDnsConfig(network);
444         assertEquals(PRIVATE_DNS_MODE_OFF, privateDnsCfg.mode);
445         assertEquals("", privateDnsCfg.hostname);
446         assertEquals(new InetAddress[0], privateDnsCfg.ips);
447 
448         // An entry with default PrivateDnsConfig is added to the PrivateDnsConfig map.
449         mDnsManager.updatePrivateDns(network, mDnsManager.getPrivateDnsConfig());
450         mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp);
451         mDnsManager.updatePrivateDnsValidation(
452                 new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, dnsAddr, "",
453                         VALIDATION_RESULT_SUCCESS));
454         mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp);
455         privateDnsCfg = mDnsManager.getPrivateDnsConfig(network);
456         assertEquals(PRIVATE_DNS_MODE_OPPORTUNISTIC, privateDnsCfg.mode);
457         assertEquals("", privateDnsCfg.hostname);
458         assertEquals(new InetAddress[0], privateDnsCfg.ips);
459 
460         // The original entry is overwritten by a new PrivateDnsConfig.
461         mDnsManager.updatePrivateDns(network, new PrivateDnsConfig(tlsName, tlsAddrs));
462         mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp);
463         privateDnsCfg = mDnsManager.getPrivateDnsConfig(network);
464         assertEquals(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, privateDnsCfg.mode);
465         assertEquals(tlsName, privateDnsCfg.hostname);
466         assertEquals(tlsAddrs, privateDnsCfg.ips);
467 
468         // The network is removed, so the PrivateDnsConfig map becomes empty again.
469         mDnsManager.removeNetwork(network);
470         privateDnsCfg = mDnsManager.getPrivateDnsConfig(network);
471         assertEquals(PRIVATE_DNS_MODE_OFF, privateDnsCfg.mode);
472         assertEquals("", privateDnsCfg.hostname);
473         assertEquals(new InetAddress[0], privateDnsCfg.ips);
474     }
475 }
476