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