• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 com.android.server.connectivity;
18 
19 import static android.net.metrics.INetdEventListener.EVENT_GETADDRINFO;
20 import static android.net.metrics.INetdEventListener.EVENT_GETHOSTBYNAME;
21 
22 import static org.junit.Assert.assertEquals;
23 import static org.junit.Assert.assertFalse;
24 import static org.junit.Assert.fail;
25 import static org.mockito.ArgumentMatchers.any;
26 import static org.mockito.Mockito.doReturn;
27 import static org.mockito.Mockito.mock;
28 import static org.mockito.Mockito.verify;
29 import static org.mockito.Mockito.when;
30 
31 import android.content.Context;
32 import android.net.ConnectivityManager;
33 import android.net.ConnectivityMetricsEvent;
34 import android.net.IIpConnectivityMetrics;
35 import android.net.IpPrefix;
36 import android.net.LinkAddress;
37 import android.net.LinkProperties;
38 import android.net.Network;
39 import android.net.NetworkCapabilities;
40 import android.net.RouteInfo;
41 import android.net.metrics.ApfProgramEvent;
42 import android.net.metrics.ApfStats;
43 import android.net.metrics.DhcpClientEvent;
44 import android.net.metrics.IpConnectivityLog;
45 import android.net.metrics.IpManagerEvent;
46 import android.net.metrics.IpReachabilityEvent;
47 import android.net.metrics.RaEvent;
48 import android.net.metrics.ValidationProbeEvent;
49 import android.os.Build;
50 import android.os.Parcelable;
51 import android.os.SystemClock;
52 import android.system.OsConstants;
53 import android.test.suitebuilder.annotation.SmallTest;
54 import android.util.Base64;
55 
56 import com.android.internal.util.BitUtils;
57 import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass;
58 import com.android.testutils.DevSdkIgnoreRule;
59 import com.android.testutils.DevSdkIgnoreRunner;
60 
61 import org.junit.Before;
62 import org.junit.Test;
63 import org.junit.runner.RunWith;
64 import org.mockito.ArgumentCaptor;
65 import org.mockito.Mock;
66 import org.mockito.MockitoAnnotations;
67 
68 import java.io.PrintWriter;
69 import java.io.StringWriter;
70 
71 @RunWith(DevSdkIgnoreRunner.class)
72 @SmallTest
73 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
74 public class IpConnectivityMetricsTest {
75     static final IpReachabilityEvent FAKE_EV =
76             new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED);
77 
78     private static final String EXAMPLE_IPV4 = "192.0.2.1";
79     private static final String EXAMPLE_IPV6 = "2001:db8:1200::2:1";
80 
81     private static final byte[] MAC_ADDR =
82             {(byte)0x84, (byte)0xc9, (byte)0xb2, (byte)0x6a, (byte)0xed, (byte)0x4b};
83     private static final long NET_HANDLE = new Network(4291).getNetworkHandle();
84 
85     @Mock Context mCtx;
86     @Mock IIpConnectivityMetrics mMockService;
87     @Mock ConnectivityManager mCm;
88 
89     IpConnectivityMetrics mService;
90     NetdEventListenerService mNetdListener;
91     private static final NetworkCapabilities CAPABILITIES_WIFI = new NetworkCapabilities.Builder()
92             .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
93             .build();
94     private static final NetworkCapabilities CAPABILITIES_CELL = new NetworkCapabilities.Builder()
95             .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
96             .build();
97 
98     @Before
setUp()99     public void setUp() {
100         MockitoAnnotations.initMocks(this);
101         mService = new IpConnectivityMetrics(mCtx, (ctx) -> 2000);
102         mNetdListener = new NetdEventListenerService(mCm);
103         mService.mNetdListener = mNetdListener;
104     }
105 
106     @Test
testBufferFlushing()107     public void testBufferFlushing() {
108         String output1 = getdump("flush");
109         assertEquals("", output1);
110 
111         new IpConnectivityLog(mService.impl).log(1, FAKE_EV);
112         String output2 = getdump("flush");
113         assertFalse("".equals(output2));
114 
115         String output3 = getdump("flush");
116         assertEquals("", output3);
117     }
118 
119     @Test
testRateLimiting()120     public void testRateLimiting() {
121         final IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
122         final ApfProgramEvent ev = new ApfProgramEvent.Builder().build();
123         final long fakeTimestamp = 1;
124 
125         int attempt = 100; // More than burst quota, but less than buffer size.
126         for (int i = 0; i < attempt; i++) {
127             logger.log(ev);
128         }
129 
130         String output1 = getdump("flush");
131         assertFalse("".equals(output1));
132 
133         for (int i = 0; i < attempt; i++) {
134             assertFalse("expected event to be dropped", logger.log(fakeTimestamp, ev));
135         }
136 
137         String output2 = getdump("flush");
138         assertEquals("", output2);
139     }
140 
logDefaultNetworkEvent(long timeMs, NetworkAgentInfo nai, NetworkAgentInfo oldNai)141     private void logDefaultNetworkEvent(long timeMs, NetworkAgentInfo nai,
142             NetworkAgentInfo oldNai) {
143         final Network network = (nai != null) ? nai.network() : null;
144         final boolean validated = (nai != null) ? nai.isValidated() : false;
145         final LinkProperties lp = (nai != null) ? nai.linkProperties : null;
146         final NetworkCapabilities nc = (nai != null) ? nai.networkCapabilities : null;
147 
148         final Network prevNetwork = (oldNai != null) ? oldNai.network() : null;
149         final LinkProperties prevLp = (oldNai != null) ? oldNai.linkProperties : null;
150         final NetworkCapabilities prevNc = (oldNai != null) ? oldNai.networkCapabilities : null;
151 
152         mService.mDefaultNetworkMetrics.logDefaultNetworkEvent(timeMs, network, 0 /* legacyScore */,
153                 validated, lp, nc, prevNetwork, 0 /* prevLegacyScore */, prevLp, prevNc);
154     }
155     @Test
testDefaultNetworkEvents()156     public void testDefaultNetworkEvents() throws Exception {
157         final long cell = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
158         final long wifi = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_WIFI});
159 
160         NetworkAgentInfo[][] defaultNetworks = {
161             // nothing -> cell
162             {null, makeNai(100, false, true, cell)},
163             // cell -> wifi
164             {makeNai(100, true, true, cell), makeNai(101, true, false, wifi)},
165             // wifi -> nothing
166             {makeNai(101, true, false, wifi), null},
167             // nothing -> cell
168             {null, makeNai(102, true, true, cell)},
169             // cell -> wifi
170             {makeNai(102, true, true, cell), makeNai(103, true, false, wifi)},
171         };
172 
173         long timeMs = mService.mDefaultNetworkMetrics.creationTimeMs;
174         long durationMs = 1001;
175         for (NetworkAgentInfo[] pair : defaultNetworks) {
176             timeMs += durationMs;
177             durationMs += durationMs;
178             logDefaultNetworkEvent(timeMs, pair[1], pair[0]);
179         }
180 
181         String want = String.join("\n",
182                 "dropped_events: 0",
183                 "events <",
184                 "  if_name: \"\"",
185                 "  link_layer: 5",
186                 "  network_id: 0",
187                 "  time_ms: 0",
188                 "  transports: 0",
189                 "  default_network_event <",
190                 "    default_network_duration_ms: 1001",
191                 "    final_score: 0",
192                 "    initial_score: 0",
193                 "    ip_support: 0",
194                 "    no_default_network_duration_ms: 0",
195                 "    previous_default_network_link_layer: 0",
196                 "    previous_network_ip_support: 0",
197                 "    validation_duration_ms: 0",
198                 "  >",
199                 ">",
200                 "events <",
201                 "  if_name: \"\"",
202                 "  link_layer: 2",
203                 "  network_id: 100",
204                 "  time_ms: 0",
205                 "  transports: 1",
206                 "  default_network_event <",
207                 "    default_network_duration_ms: 2002",
208                 "    final_score: 0",
209                 "    initial_score: 0",
210                 "    ip_support: 3",
211                 "    no_default_network_duration_ms: 0",
212                 "    previous_default_network_link_layer: 0",
213                 "    previous_network_ip_support: 0",
214                 "    validation_duration_ms: 2002",
215                 "  >",
216                 ">",
217                 "events <",
218                 "  if_name: \"\"",
219                 "  link_layer: 4",
220                 "  network_id: 101",
221                 "  time_ms: 0",
222                 "  transports: 2",
223                 "  default_network_event <",
224                 "    default_network_duration_ms: 4004",
225                 "    final_score: 0",
226                 "    initial_score: 0",
227                 "    ip_support: 1",
228                 "    no_default_network_duration_ms: 0",
229                 "    previous_default_network_link_layer: 2",
230                 "    previous_network_ip_support: 0",
231                 "    validation_duration_ms: 4004",
232                 "  >",
233                 ">",
234                 "events <",
235                 "  if_name: \"\"",
236                 "  link_layer: 5",
237                 "  network_id: 0",
238                 "  time_ms: 0",
239                 "  transports: 0",
240                 "  default_network_event <",
241                 "    default_network_duration_ms: 8008",
242                 "    final_score: 0",
243                 "    initial_score: 0",
244                 "    ip_support: 0",
245                 "    no_default_network_duration_ms: 0",
246                 "    previous_default_network_link_layer: 4",
247                 "    previous_network_ip_support: 0",
248                 "    validation_duration_ms: 0",
249                 "  >",
250                 ">",
251                 "events <",
252                 "  if_name: \"\"",
253                 "  link_layer: 2",
254                 "  network_id: 102",
255                 "  time_ms: 0",
256                 "  transports: 1",
257                 "  default_network_event <",
258                 "    default_network_duration_ms: 16016",
259                 "    final_score: 0",
260                 "    initial_score: 0",
261                 "    ip_support: 3",
262                 "    no_default_network_duration_ms: 0",
263                 "    previous_default_network_link_layer: 4",
264                 "    previous_network_ip_support: 0",
265                 "    validation_duration_ms: 16016",
266                 "  >",
267                 ">",
268                 "version: 2\n");
269 
270         verifySerialization(want, getdump("flush"));
271     }
272 
273     @Test
testEndToEndLogging()274     public void testEndToEndLogging() throws Exception {
275         // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
276         IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
277 
278         ApfStats apfStats = new ApfStats.Builder()
279                 .setDurationMs(45000)
280                 .setReceivedRas(10)
281                 .setMatchingRas(2)
282                 .setDroppedRas(2)
283                 .setParseErrors(2)
284                 .setZeroLifetimeRas(1)
285                 .setProgramUpdates(4)
286                 .setProgramUpdatesAll(7)
287                 .setProgramUpdatesAllowingMulticast(3)
288                 .setMaxProgramSize(2048)
289                 .build();
290 
291         final ValidationProbeEvent validationEv = new ValidationProbeEvent.Builder()
292                 .setDurationMs(40730)
293                 .setProbeType(ValidationProbeEvent.PROBE_HTTP, true)
294                 .setReturnCode(204)
295                 .build();
296 
297         final DhcpClientEvent event = new DhcpClientEvent.Builder()
298                 .setMsg("SomeState")
299                 .setDurationMs(192)
300                 .build();
301         Parcelable[] events = {
302             new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED), event,
303             new IpManagerEvent(IpManagerEvent.PROVISIONING_OK, 5678),
304             validationEv,
305             apfStats,
306             new RaEvent(2000, 400, 300, -1, 1000, -1)
307         };
308 
309         for (int i = 0; i < events.length; i++) {
310             ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
311             ev.timestamp = 100 * (i + 1);
312             ev.ifname = "wlan0";
313             ev.data = events[i];
314             logger.log(ev);
315         }
316 
317         // netId, errno, latency, destination
318         connectEvent(100, OsConstants.EALREADY, 0, EXAMPLE_IPV4);
319         connectEvent(100, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6);
320         connectEvent(100, 0, 110, EXAMPLE_IPV4);
321         connectEvent(101, 0, 23, EXAMPLE_IPV4);
322         connectEvent(101, 0, 45, EXAMPLE_IPV6);
323         connectEvent(100, OsConstants.EAGAIN, 0, EXAMPLE_IPV4);
324 
325         // netId, type, return code, latency
326         dnsEvent(100, EVENT_GETADDRINFO, 0, 3456);
327         dnsEvent(100, EVENT_GETADDRINFO, 3, 45);
328         dnsEvent(100, EVENT_GETHOSTBYNAME, 0, 638);
329         dnsEvent(101, EVENT_GETADDRINFO, 0, 56);
330         dnsEvent(101, EVENT_GETHOSTBYNAME, 0, 34);
331 
332         // iface, uid
333         final byte[] mac = {0x48, 0x7c, 0x2b, 0x6a, 0x3e, 0x4b};
334         final String srcIp = "192.168.2.1";
335         final String dstIp = "192.168.2.23";
336         final int sport = 2356;
337         final int dport = 13489;
338         final long now = 1001L;
339         final int v4 = 0x800;
340         final int tcp = 6;
341         final int udp = 17;
342         wakeupEvent("wlan0", 1000, v4, tcp, mac, srcIp, dstIp, sport, dport, 1001L);
343         wakeupEvent("wlan0", 10123, v4, tcp, mac, srcIp, dstIp, sport, dport, 1001L);
344         wakeupEvent("wlan0", 1000, v4, udp, mac, srcIp, dstIp, sport, dport, 1001L);
345         wakeupEvent("wlan0", 10008, v4, udp, mac, srcIp, dstIp, sport, dport, 1001L);
346         wakeupEvent("wlan0", -1, v4, udp, mac, srcIp, dstIp, sport, dport, 1001L);
347         wakeupEvent("wlan0", 10008, v4, tcp, mac, srcIp, dstIp, sport, dport, 1001L);
348 
349         long timeMs = mService.mDefaultNetworkMetrics.creationTimeMs;
350         final long cell = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
351         final long wifi = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_WIFI});
352         final NetworkAgentInfo cellNai = makeNai(100, false, true, cell);
353         final NetworkAgentInfo wifiNai = makeNai(101, true, false, wifi);
354         logDefaultNetworkEvent(timeMs + 200L, cellNai, null);
355         logDefaultNetworkEvent(timeMs + 300L, wifiNai, cellNai);
356 
357         String want = String.join("\n",
358                 "dropped_events: 0",
359                 "events <",
360                 "  if_name: \"\"",
361                 "  link_layer: 4",
362                 "  network_id: 0",
363                 "  time_ms: 100",
364                 "  transports: 0",
365                 "  ip_reachability_event <",
366                 "    event_type: 512",
367                 "    if_name: \"\"",
368                 "  >",
369                 ">",
370                 "events <",
371                 "  if_name: \"\"",
372                 "  link_layer: 4",
373                 "  network_id: 0",
374                 "  time_ms: 200",
375                 "  transports: 0",
376                 "  dhcp_event <",
377                 "    duration_ms: 192",
378                 "    if_name: \"\"",
379                 "    state_transition: \"SomeState\"",
380                 "  >",
381                 ">",
382                 "events <",
383                 "  if_name: \"\"",
384                 "  link_layer: 4",
385                 "  network_id: 0",
386                 "  time_ms: 300",
387                 "  transports: 0",
388                 "  ip_provisioning_event <",
389                 "    event_type: 1",
390                 "    if_name: \"\"",
391                 "    latency_ms: 5678",
392                 "  >",
393                 ">",
394                 "events <",
395                 "  if_name: \"\"",
396                 "  link_layer: 4",
397                 "  network_id: 0",
398                 "  time_ms: 400",
399                 "  transports: 0",
400                 "  validation_probe_event <",
401                 "    latency_ms: 40730",
402                 "    probe_result: 204",
403                 "    probe_type: 257",
404                 "  >",
405                 ">",
406                 "events <",
407                 "  if_name: \"\"",
408                 "  link_layer: 4",
409                 "  network_id: 0",
410                 "  time_ms: 500",
411                 "  transports: 0",
412                 "  apf_statistics <",
413                 "    dropped_ras: 2",
414                 "    duration_ms: 45000",
415                 "    matching_ras: 2",
416                 "    max_program_size: 2048",
417                 "    parse_errors: 2",
418                 "    program_updates: 4",
419                 "    program_updates_all: 7",
420                 "    program_updates_allowing_multicast: 3",
421                 "    received_ras: 10",
422                 "    total_packet_dropped: 0",
423                 "    total_packet_processed: 0",
424                 "    zero_lifetime_ras: 1",
425                 "  >",
426                 ">",
427                 "events <",
428                 "  if_name: \"\"",
429                 "  link_layer: 4",
430                 "  network_id: 0",
431                 "  time_ms: 600",
432                 "  transports: 0",
433                 "  ra_event <",
434                 "    dnssl_lifetime: -1",
435                 "    prefix_preferred_lifetime: 300",
436                 "    prefix_valid_lifetime: 400",
437                 "    rdnss_lifetime: 1000",
438                 "    route_info_lifetime: -1",
439                 "    router_lifetime: 2000",
440                 "  >",
441                 ">",
442                 "events <",
443                 "  if_name: \"\"",
444                 "  link_layer: 5",
445                 "  network_id: 0",
446                 "  time_ms: 0",
447                 "  transports: 0",
448                 "  default_network_event <",
449                 "    default_network_duration_ms: 200",
450                 "    final_score: 0",
451                 "    initial_score: 0",
452                 "    ip_support: 0",
453                 "    no_default_network_duration_ms: 0",
454                 "    previous_default_network_link_layer: 0",
455                 "    previous_network_ip_support: 0",
456                 "    validation_duration_ms: 0",
457                 "  >",
458                 ">",
459                 "events <",
460                 "  if_name: \"\"",
461                 "  link_layer: 2",
462                 "  network_id: 100",
463                 "  time_ms: 0",
464                 "  transports: 1",
465                 "  default_network_event <",
466                 "    default_network_duration_ms: 100",
467                 "    final_score: 0",
468                 "    initial_score: 0",
469                 "    ip_support: 2",
470                 "    no_default_network_duration_ms: 0",
471                 "    previous_default_network_link_layer: 0",
472                 "    previous_network_ip_support: 0",
473                 "    validation_duration_ms: 100",
474                 "  >",
475                 ">",
476                 "events <",
477                 "  if_name: \"\"",
478                 "  link_layer: 4",
479                 "  network_id: 100",
480                 "  time_ms: 0",
481                 "  transports: 2",
482                 "  connect_statistics <",
483                 "    connect_blocking_count: 1",
484                 "    connect_count: 3",
485                 "    errnos_counters <",
486                 "      key: 11",
487                 "      value: 1",
488                 "    >",
489                 "    ipv6_addr_count: 1",
490                 "    latencies_ms: 110",
491                 "  >",
492                 ">",
493                 "events <",
494                 "  if_name: \"\"",
495                 "  link_layer: 2",
496                 "  network_id: 101",
497                 "  time_ms: 0",
498                 "  transports: 1",
499                 "  connect_statistics <",
500                 "    connect_blocking_count: 2",
501                 "    connect_count: 2",
502                 "    ipv6_addr_count: 1",
503                 "    latencies_ms: 23",
504                 "    latencies_ms: 45",
505                 "  >",
506                 ">",
507                 "events <",
508                 "  if_name: \"\"",
509                 "  link_layer: 4",
510                 "  network_id: 100",
511                 "  time_ms: 0",
512                 "  transports: 2",
513                 "  dns_lookup_batch <",
514                 "    event_types: 1",
515                 "    event_types: 1",
516                 "    event_types: 2",
517                 "    getaddrinfo_error_count: 0",
518                 "    getaddrinfo_query_count: 0",
519                 "    gethostbyname_error_count: 0",
520                 "    gethostbyname_query_count: 0",
521                 "    latencies_ms: 3456",
522                 "    latencies_ms: 45",
523                 "    latencies_ms: 638",
524                 "    return_codes: 0",
525                 "    return_codes: 3",
526                 "    return_codes: 0",
527                 "  >",
528                 ">",
529                 "events <",
530                 "  if_name: \"\"",
531                 "  link_layer: 2",
532                 "  network_id: 101",
533                 "  time_ms: 0",
534                 "  transports: 1",
535                 "  dns_lookup_batch <",
536                 "    event_types: 1",
537                 "    event_types: 2",
538                 "    getaddrinfo_error_count: 0",
539                 "    getaddrinfo_query_count: 0",
540                 "    gethostbyname_error_count: 0",
541                 "    gethostbyname_query_count: 0",
542                 "    latencies_ms: 56",
543                 "    latencies_ms: 34",
544                 "    return_codes: 0",
545                 "    return_codes: 0",
546                 "  >",
547                 ">",
548                 "events <",
549                 "  if_name: \"\"",
550                 "  link_layer: 4",
551                 "  network_id: 0",
552                 "  time_ms: 0",
553                 "  transports: 0",
554                 "  wakeup_stats <",
555                 "    application_wakeups: 3",
556                 "    duration_sec: 0",
557                 "    ethertype_counts <",
558                 "      key: 2048",
559                 "      value: 6",
560                 "    >",
561                 "    ip_next_header_counts <",
562                 "      key: 6",
563                 "      value: 3",
564                 "    >",
565                 "    ip_next_header_counts <",
566                 "      key: 17",
567                 "      value: 3",
568                 "    >",
569                 "    l2_broadcast_count: 0",
570                 "    l2_multicast_count: 0",
571                 "    l2_unicast_count: 6",
572                 "    no_uid_wakeups: 1",
573                 "    non_application_wakeups: 0",
574                 "    root_wakeups: 0",
575                 "    system_wakeups: 2",
576                 "    total_wakeups: 6",
577                 "  >",
578                 ">",
579                 "version: 2\n");
580 
581         verifySerialization(want, getdump("flush"));
582     }
583 
getdump(String .... command)584     String getdump(String ... command) {
585         StringWriter buffer = new StringWriter();
586         PrintWriter writer = new PrintWriter(buffer);
587         mService.impl.dump(null, writer, command);
588         return buffer.toString();
589     }
590 
setCapabilities(int netId)591     private void setCapabilities(int netId) {
592         final ArgumentCaptor<ConnectivityManager.NetworkCallback> networkCallback =
593                 ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
594         verify(mCm).registerNetworkCallback(any(), networkCallback.capture());
595         networkCallback.getValue().onCapabilitiesChanged(new Network(netId),
596                 netId == 100 ? CAPABILITIES_WIFI : CAPABILITIES_CELL);
597     }
598 
connectEvent(int netId, int error, int latencyMs, String ipAddr)599     void connectEvent(int netId, int error, int latencyMs, String ipAddr) throws Exception {
600         setCapabilities(netId);
601         mNetdListener.onConnectEvent(netId, error, latencyMs, ipAddr, 80, 1);
602     }
603 
dnsEvent(int netId, int type, int result, int latency)604     void dnsEvent(int netId, int type, int result, int latency) throws Exception {
605         setCapabilities(netId);
606         mNetdListener.onDnsEvent(netId, type, result, latency, "", null, 0, 0);
607     }
608 
wakeupEvent(String iface, int uid, int ether, int ip, byte[] mac, String srcIp, String dstIp, int sport, int dport, long now)609     void wakeupEvent(String iface, int uid, int ether, int ip, byte[] mac, String srcIp,
610             String dstIp, int sport, int dport, long now) throws Exception {
611         String prefix = NET_HANDLE + ":" + iface;
612         mNetdListener.onWakeupEvent(prefix, uid, ether, ip, mac, srcIp, dstIp, sport, dport, now);
613     }
614 
makeNai(int netId, boolean ipv4, boolean ipv6, long transports)615     NetworkAgentInfo makeNai(int netId, boolean ipv4, boolean ipv6, long transports) {
616         NetworkAgentInfo nai = mock(NetworkAgentInfo.class);
617         when(nai.network()).thenReturn(new Network(netId));
618         nai.linkProperties = new LinkProperties();
619         nai.networkCapabilities = new NetworkCapabilities();
620         nai.setValidated(true);
621         doReturn(true).when(nai).isValidated();
622         doReturn(SystemClock.elapsedRealtime()).when(nai).getFirstValidationTime();
623         doReturn(SystemClock.elapsedRealtime()).when(nai).getCurrentValidationTime();
624         for (int t : BitUtils.unpackBits(transports)) {
625             nai.networkCapabilities.addTransportType(t);
626         }
627         if (ipv4) {
628             nai.linkProperties.addLinkAddress(new LinkAddress("192.0.2.12/24"));
629             nai.linkProperties.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0")));
630         }
631         if (ipv6) {
632             nai.linkProperties.addLinkAddress(new LinkAddress("2001:db8:dead:beef:f00::a0/64"));
633             nai.linkProperties.addRoute(new RouteInfo(new IpPrefix("::/0")));
634         }
635         return nai;
636     }
637 
verifySerialization(String want, String output)638     static void verifySerialization(String want, String output) {
639         try {
640             byte[] got = Base64.decode(output, Base64.DEFAULT);
641             IpConnectivityLogClass.IpConnectivityLog log =
642                     IpConnectivityLogClass.IpConnectivityLog.parseFrom(got);
643             assertEquals(want, log.toString());
644         } catch (Exception e) {
645             fail(e.toString());
646         }
647     }
648 }
649