blob: d5b2c87ffe463236ad2a9b3d4cd27a9141ac61b8 [file] [log] [blame]
Hugo Benichi00a42d42016-09-13 15:55:09 +09001/*
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
17package com.android.server.connectivity;
18
Hugo Benichi5eb90532017-03-23 18:38:22 +090019import static android.net.metrics.INetdEventListener.EVENT_GETADDRINFO;
20import static android.net.metrics.INetdEventListener.EVENT_GETHOSTBYNAME;
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +090021
Hugo Benichi5eb90532017-03-23 18:38:22 +090022import static org.junit.Assert.assertEquals;
23import static org.junit.Assert.assertFalse;
24import static org.junit.Assert.assertTrue;
25import static org.junit.Assert.fail;
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +090026import static org.mockito.Mockito.mock;
27import static org.mockito.Mockito.timeout;
28import static org.mockito.Mockito.verify;
29import static org.mockito.Mockito.when;
Glen Kuhne07199402016-10-25 15:47:25 -070030
Hugo Benichi00a42d42016-09-13 15:55:09 +090031import android.content.Context;
Hugo Benichi5eb90532017-03-23 18:38:22 +090032import android.net.ConnectivityManager;
Hugo Benichi00a42d42016-09-13 15:55:09 +090033import android.net.ConnectivityMetricsEvent;
34import android.net.IIpConnectivityMetrics;
Hugo Benichi1193a9c2017-10-19 14:58:15 +090035import android.net.IpPrefix;
36import android.net.LinkAddress;
37import android.net.LinkProperties;
Hugo Benichi5eb90532017-03-23 18:38:22 +090038import android.net.Network;
39import android.net.NetworkCapabilities;
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +090040import android.net.RouteInfo;
Hugo Benichie1c173d2016-10-18 10:36:33 +090041import android.net.metrics.ApfProgramEvent;
Hugo Benichi00a42d42016-09-13 15:55:09 +090042import android.net.metrics.ApfStats;
Hugo Benichi00a42d42016-09-13 15:55:09 +090043import android.net.metrics.DhcpClientEvent;
44import android.net.metrics.IpConnectivityLog;
45import android.net.metrics.IpManagerEvent;
46import android.net.metrics.IpReachabilityEvent;
47import android.net.metrics.RaEvent;
48import android.net.metrics.ValidationProbeEvent;
49import android.os.Parcelable;
Hugo Benichi1193a9c2017-10-19 14:58:15 +090050import android.system.OsConstants;
Hugo Benichi80df43e2016-11-24 11:28:06 +090051import android.test.suitebuilder.annotation.SmallTest;
Hugo Benichi00a42d42016-09-13 15:55:09 +090052import android.util.Base64;
Hugo Benichi1193a9c2017-10-19 14:58:15 +090053
Brett Chabot1ae2aa62019-03-04 14:14:56 -080054import androidx.test.runner.AndroidJUnit4;
55
Hugo Benichi1193a9c2017-10-19 14:58:15 +090056import com.android.internal.util.BitUtils;
Tamas Berghammer383db5eb2016-06-22 15:21:38 +010057import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass;
Hugo Benichi1193a9c2017-10-19 14:58:15 +090058
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +090059import org.junit.Before;
60import org.junit.Test;
61import org.junit.runner.RunWith;
62import org.mockito.ArgumentCaptor;
63import org.mockito.Mock;
64import org.mockito.MockitoAnnotations;
65
Hugo Benichi00a42d42016-09-13 15:55:09 +090066import java.io.PrintWriter;
67import java.io.StringWriter;
68import java.util.Collections;
69import java.util.Comparator;
70import java.util.Iterator;
71import java.util.List;
Hugo Benichi1193a9c2017-10-19 14:58:15 +090072
Hugo Benichi5eb90532017-03-23 18:38:22 +090073@RunWith(AndroidJUnit4.class)
74@SmallTest
75public class IpConnectivityMetricsTest {
Hugo Benichi00a42d42016-09-13 15:55:09 +090076 static final IpReachabilityEvent FAKE_EV =
Hugo Benichi948a8592017-03-16 16:33:47 +090077 new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED);
Hugo Benichi00a42d42016-09-13 15:55:09 +090078
Hugo Benichi5eb90532017-03-23 18:38:22 +090079 private static final String EXAMPLE_IPV4 = "192.0.2.1";
80 private static final String EXAMPLE_IPV6 = "2001:db8:1200::2:1";
81
Hugo Benichid921bce2017-10-12 21:33:40 +090082 private static final byte[] MAC_ADDR =
83 {(byte)0x84, (byte)0xc9, (byte)0xb2, (byte)0x6a, (byte)0xed, (byte)0x4b};
84
Hugo Benichi00a42d42016-09-13 15:55:09 +090085 @Mock Context mCtx;
86 @Mock IIpConnectivityMetrics mMockService;
Hugo Benichi5eb90532017-03-23 18:38:22 +090087 @Mock ConnectivityManager mCm;
Hugo Benichi00a42d42016-09-13 15:55:09 +090088
89 IpConnectivityMetrics mService;
Hugo Benichi5eb90532017-03-23 18:38:22 +090090 NetdEventListenerService mNetdListener;
Hugo Benichi00a42d42016-09-13 15:55:09 +090091
Hugo Benichi5eb90532017-03-23 18:38:22 +090092 @Before
Hugo Benichi00a42d42016-09-13 15:55:09 +090093 public void setUp() {
94 MockitoAnnotations.initMocks(this);
Hugo Benichi05686db2016-10-19 11:17:28 +090095 mService = new IpConnectivityMetrics(mCtx, (ctx) -> 2000);
Hugo Benichi5eb90532017-03-23 18:38:22 +090096 mNetdListener = new NetdEventListenerService(mCm);
97 mService.mNetdListener = mNetdListener;
Hugo Benichi00a42d42016-09-13 15:55:09 +090098 }
99
Hugo Benichi5eb90532017-03-23 18:38:22 +0900100 @Test
Hugo Benichi00a42d42016-09-13 15:55:09 +0900101 public void testLoggingEvents() throws Exception {
102 IpConnectivityLog logger = new IpConnectivityLog(mMockService);
103
104 assertTrue(logger.log(1, FAKE_EV));
105 assertTrue(logger.log(2, FAKE_EV));
106 assertTrue(logger.log(3, FAKE_EV));
107
108 List<ConnectivityMetricsEvent> got = verifyEvents(3);
109 assertEventsEqual(expectedEvent(1), got.get(0));
110 assertEventsEqual(expectedEvent(2), got.get(1));
111 assertEventsEqual(expectedEvent(3), got.get(2));
112 }
113
Hugo Benichi5eb90532017-03-23 18:38:22 +0900114 @Test
Hugo Benichi00a42d42016-09-13 15:55:09 +0900115 public void testLoggingEventsWithMultipleCallers() throws Exception {
116 IpConnectivityLog logger = new IpConnectivityLog(mMockService);
117
118 final int nCallers = 10;
119 final int nEvents = 10;
120 for (int n = 0; n < nCallers; n++) {
121 final int i = n;
122 new Thread() {
123 public void run() {
124 for (int j = 0; j < nEvents; j++) {
Hugo Benichi946b7e42017-03-15 16:35:26 +0900125 assertTrue(logger.log(1 + i * 100 + j, FAKE_EV));
Hugo Benichi00a42d42016-09-13 15:55:09 +0900126 }
127 }
128 }.start();
129 }
130
Hugo Benichi5eb90532017-03-23 18:38:22 +0900131 List<ConnectivityMetricsEvent> got = verifyEvents(nCallers * nEvents, 200);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900132 Collections.sort(got, EVENT_COMPARATOR);
133 Iterator<ConnectivityMetricsEvent> iter = got.iterator();
134 for (int i = 0; i < nCallers; i++) {
135 for (int j = 0; j < nEvents; j++) {
Hugo Benichi946b7e42017-03-15 16:35:26 +0900136 int expectedTimestamp = 1 + i * 100 + j;
Hugo Benichi00a42d42016-09-13 15:55:09 +0900137 assertEventsEqual(expectedEvent(expectedTimestamp), iter.next());
138 }
139 }
140 }
141
Hugo Benichi5eb90532017-03-23 18:38:22 +0900142 @Test
Hugo Benichi00a42d42016-09-13 15:55:09 +0900143 public void testBufferFlushing() {
144 String output1 = getdump("flush");
145 assertEquals("", output1);
146
147 new IpConnectivityLog(mService.impl).log(1, FAKE_EV);
148 String output2 = getdump("flush");
149 assertFalse("".equals(output2));
150
151 String output3 = getdump("flush");
152 assertEquals("", output3);
153 }
154
Hugo Benichi5eb90532017-03-23 18:38:22 +0900155 @Test
Hugo Benichie1c173d2016-10-18 10:36:33 +0900156 public void testRateLimiting() {
157 final IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +0900158 final ApfProgramEvent ev = new ApfProgramEvent.Builder().build();
Hugo Benichie1c173d2016-10-18 10:36:33 +0900159 final long fakeTimestamp = 1;
160
161 int attempt = 100; // More than burst quota, but less than buffer size.
162 for (int i = 0; i < attempt; i++) {
163 logger.log(ev);
164 }
165
166 String output1 = getdump("flush");
167 assertFalse("".equals(output1));
168
169 for (int i = 0; i < attempt; i++) {
170 assertFalse("expected event to be dropped", logger.log(fakeTimestamp, ev));
171 }
172
173 String output2 = getdump("flush");
174 assertEquals("", output2);
175 }
176
Hugo Benichi5eb90532017-03-23 18:38:22 +0900177 @Test
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900178 public void testDefaultNetworkEvents() throws Exception {
179 final long cell = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
180 final long wifi = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_WIFI});
181
182 NetworkAgentInfo[][] defaultNetworks = {
183 // nothing -> cell
184 {null, makeNai(100, 10, false, true, cell)},
185 // cell -> wifi
186 {makeNai(100, 50, true, true, cell), makeNai(101, 20, true, false, wifi)},
187 // wifi -> nothing
188 {makeNai(101, 60, true, false, wifi), null},
189 // nothing -> cell
190 {null, makeNai(102, 10, true, true, cell)},
191 // cell -> wifi
192 {makeNai(102, 50, true, true, cell), makeNai(103, 20, true, false, wifi)},
193 };
194
Hugo Benichi380a0632017-10-20 09:25:29 +0900195 long timeMs = mService.mDefaultNetworkMetrics.creationTimeMs;
196 long durationMs = 1001;
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900197 for (NetworkAgentInfo[] pair : defaultNetworks) {
Hugo Benichi380a0632017-10-20 09:25:29 +0900198 timeMs += durationMs;
199 durationMs += durationMs;
200 mService.mDefaultNetworkMetrics.logDefaultNetworkEvent(timeMs, pair[1], pair[0]);
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900201 }
202
203 String want = String.join("\n",
204 "dropped_events: 0",
205 "events <",
206 " if_name: \"\"",
Hugo Benichi380a0632017-10-20 09:25:29 +0900207 " link_layer: 5",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900208 " network_id: 0",
209 " time_ms: 0",
210 " transports: 0",
211 " default_network_event <",
Hugo Benichi380a0632017-10-20 09:25:29 +0900212 " default_network_duration_ms: 1001",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900213 " final_score: 0",
214 " initial_score: 0",
215 " ip_support: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900216 " no_default_network_duration_ms: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900217 " previous_default_network_link_layer: 0",
218 " previous_network_ip_support: 0",
219 " validation_duration_ms: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900220 " >",
221 ">",
222 "events <",
223 " if_name: \"\"",
Hugo Benichi380a0632017-10-20 09:25:29 +0900224 " link_layer: 2",
225 " network_id: 100",
226 " time_ms: 0",
227 " transports: 1",
228 " default_network_event <",
229 " default_network_duration_ms: 2002",
230 " final_score: 50",
231 " initial_score: 10",
232 " ip_support: 3",
233 " no_default_network_duration_ms: 0",
234 " previous_default_network_link_layer: 0",
235 " previous_network_ip_support: 0",
236 " validation_duration_ms: 2002",
237 " >",
238 ">",
239 "events <",
240 " if_name: \"\"",
241 " link_layer: 4",
242 " network_id: 101",
243 " time_ms: 0",
244 " transports: 2",
245 " default_network_event <",
246 " default_network_duration_ms: 4004",
247 " final_score: 60",
248 " initial_score: 20",
249 " ip_support: 1",
250 " no_default_network_duration_ms: 0",
251 " previous_default_network_link_layer: 2",
252 " previous_network_ip_support: 0",
253 " validation_duration_ms: 4004",
254 " >",
255 ">",
256 "events <",
257 " if_name: \"\"",
258 " link_layer: 5",
259 " network_id: 0",
260 " time_ms: 0",
261 " transports: 0",
262 " default_network_event <",
263 " default_network_duration_ms: 8008",
264 " final_score: 0",
265 " initial_score: 0",
266 " ip_support: 0",
267 " no_default_network_duration_ms: 0",
268 " previous_default_network_link_layer: 4",
269 " previous_network_ip_support: 0",
270 " validation_duration_ms: 0",
271 " >",
272 ">",
273 "events <",
274 " if_name: \"\"",
275 " link_layer: 2",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900276 " network_id: 102",
277 " time_ms: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900278 " transports: 1",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900279 " default_network_event <",
Hugo Benichi380a0632017-10-20 09:25:29 +0900280 " default_network_duration_ms: 16016",
281 " final_score: 50",
282 " initial_score: 10",
283 " ip_support: 3",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900284 " no_default_network_duration_ms: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900285 " previous_default_network_link_layer: 4",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900286 " previous_network_ip_support: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900287 " validation_duration_ms: 16016",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900288 " >",
289 ">",
290 "version: 2\n");
291
292 verifySerialization(want, getdump("flush"));
293 }
294
295 @Test
Hugo Benichi5eb90532017-03-23 18:38:22 +0900296 public void testEndToEndLogging() throws Exception {
Hugo Benichif6840502017-03-08 11:59:36 +0900297 // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
Hugo Benichi00a42d42016-09-13 15:55:09 +0900298 IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
299
Hugo Benichi5eb90532017-03-23 18:38:22 +0900300 NetworkCapabilities ncWifi = new NetworkCapabilities();
301 NetworkCapabilities ncCell = new NetworkCapabilities();
302 ncWifi.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
303 ncCell.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
304
305 when(mCm.getNetworkCapabilities(new Network(100))).thenReturn(ncWifi);
306 when(mCm.getNetworkCapabilities(new Network(101))).thenReturn(ncCell);
307
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +0900308 ApfStats apfStats = new ApfStats.Builder()
309 .setDurationMs(45000)
310 .setReceivedRas(10)
311 .setMatchingRas(2)
312 .setDroppedRas(2)
313 .setParseErrors(2)
314 .setZeroLifetimeRas(1)
315 .setProgramUpdates(4)
316 .setProgramUpdatesAll(7)
317 .setProgramUpdatesAllowingMulticast(3)
318 .setMaxProgramSize(2048)
319 .build();
Hugo Benichif927f0c2017-03-17 15:42:40 +0900320
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +0900321 final ValidationProbeEvent validationEv = new ValidationProbeEvent.Builder()
322 .setDurationMs(40730)
323 .setProbeType(ValidationProbeEvent.PROBE_HTTP, true)
324 .setReturnCode(204)
325 .build();
Hugo Benichif927f0c2017-03-17 15:42:40 +0900326
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +0900327 final DhcpClientEvent event = new DhcpClientEvent.Builder()
328 .setMsg("SomeState")
329 .setDurationMs(192)
330 .build();
Hugo Benichi00a42d42016-09-13 15:55:09 +0900331 Parcelable[] events = {
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +0900332 new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED), event,
Hugo Benichi948a8592017-03-16 16:33:47 +0900333 new IpManagerEvent(IpManagerEvent.PROVISIONING_OK, 5678),
Hugo Benichif927f0c2017-03-17 15:42:40 +0900334 validationEv,
Hugo Benichi22d9b2d2017-02-22 13:02:27 +0900335 apfStats,
Hugo Benichi00a42d42016-09-13 15:55:09 +0900336 new RaEvent(2000, 400, 300, -1, 1000, -1)
337 };
338
339 for (int i = 0; i < events.length; i++) {
Hugo Benichi948a8592017-03-16 16:33:47 +0900340 ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
341 ev.timestamp = 100 * (i + 1);
342 ev.ifname = "wlan0";
343 ev.data = events[i];
344 logger.log(ev);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900345 }
346
Hugo Benichi5eb90532017-03-23 18:38:22 +0900347 // netId, errno, latency, destination
348 connectEvent(100, OsConstants.EALREADY, 0, EXAMPLE_IPV4);
349 connectEvent(100, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6);
350 connectEvent(100, 0, 110, EXAMPLE_IPV4);
351 connectEvent(101, 0, 23, EXAMPLE_IPV4);
352 connectEvent(101, 0, 45, EXAMPLE_IPV6);
353 connectEvent(100, OsConstants.EAGAIN, 0, EXAMPLE_IPV4);
354
355 // netId, type, return code, latency
356 dnsEvent(100, EVENT_GETADDRINFO, 0, 3456);
357 dnsEvent(100, EVENT_GETADDRINFO, 3, 45);
358 dnsEvent(100, EVENT_GETHOSTBYNAME, 0, 638);
359 dnsEvent(101, EVENT_GETADDRINFO, 0, 56);
360 dnsEvent(101, EVENT_GETHOSTBYNAME, 0, 34);
361
Hugo Benichi60c9f632017-09-05 13:34:48 +0900362 // iface, uid
Hugo Benichid921bce2017-10-12 21:33:40 +0900363 final byte[] mac = {0x48, 0x7c, 0x2b, 0x6a, 0x3e, 0x4b};
364 final String srcIp = "192.168.2.1";
365 final String dstIp = "192.168.2.23";
366 final int sport = 2356;
367 final int dport = 13489;
368 final long now = 1001L;
369 final int v4 = 0x800;
370 final int tcp = 6;
371 final int udp = 17;
372 wakeupEvent("wlan0", 1000, v4, tcp, mac, srcIp, dstIp, sport, dport, 1001L);
373 wakeupEvent("wlan0", 10123, v4, tcp, mac, srcIp, dstIp, sport, dport, 1001L);
374 wakeupEvent("wlan0", 1000, v4, udp, mac, srcIp, dstIp, sport, dport, 1001L);
375 wakeupEvent("wlan0", 10008, v4, udp, mac, srcIp, dstIp, sport, dport, 1001L);
376 wakeupEvent("wlan0", -1, v4, udp, mac, srcIp, dstIp, sport, dport, 1001L);
377 wakeupEvent("wlan0", 10008, v4, tcp, mac, srcIp, dstIp, sport, dport, 1001L);
Hugo Benichi60c9f632017-09-05 13:34:48 +0900378
Hugo Benichi380a0632017-10-20 09:25:29 +0900379 long timeMs = mService.mDefaultNetworkMetrics.creationTimeMs;
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900380 final long cell = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
381 final long wifi = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_WIFI});
382 NetworkAgentInfo cellNai = makeNai(100, 50, false, true, cell);
383 NetworkAgentInfo wifiNai = makeNai(101, 60, true, false, wifi);
Hugo Benichi380a0632017-10-20 09:25:29 +0900384 mService.mDefaultNetworkMetrics.logDefaultNetworkEvent(timeMs + 200, cellNai, null);
385 mService.mDefaultNetworkMetrics.logDefaultNetworkEvent(timeMs + 300, wifiNai, cellNai);
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900386
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900387 String want = String.join("\n",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900388 "dropped_events: 0",
389 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900390 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900391 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900392 " network_id: 0",
Hugo Benichi80df43e2016-11-24 11:28:06 +0900393 " time_ms: 100",
Hugo Benichif6840502017-03-08 11:59:36 +0900394 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900395 " ip_reachability_event <",
396 " event_type: 512",
Hugo Benichi948a8592017-03-16 16:33:47 +0900397 " if_name: \"\"",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900398 " >",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900399 ">",
400 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900401 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900402 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900403 " network_id: 0",
Hugo Benichi80df43e2016-11-24 11:28:06 +0900404 " time_ms: 200",
Hugo Benichif6840502017-03-08 11:59:36 +0900405 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900406 " dhcp_event <",
407 " duration_ms: 192",
Hugo Benichi948a8592017-03-16 16:33:47 +0900408 " if_name: \"\"",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900409 " state_transition: \"SomeState\"",
410 " >",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900411 ">",
412 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900413 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900414 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900415 " network_id: 0",
Hugo Benichi80df43e2016-11-24 11:28:06 +0900416 " time_ms: 300",
Hugo Benichif6840502017-03-08 11:59:36 +0900417 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900418 " ip_provisioning_event <",
419 " event_type: 1",
Hugo Benichi948a8592017-03-16 16:33:47 +0900420 " if_name: \"\"",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900421 " latency_ms: 5678",
422 " >",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900423 ">",
424 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900425 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900426 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900427 " network_id: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900428 " time_ms: 400",
Hugo Benichif6840502017-03-08 11:59:36 +0900429 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900430 " validation_probe_event <",
431 " latency_ms: 40730",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900432 " probe_result: 204",
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +0900433 " probe_type: 257",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900434 " >",
435 ">",
436 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900437 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900438 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900439 " network_id: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900440 " time_ms: 500",
Hugo Benichif6840502017-03-08 11:59:36 +0900441 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900442 " apf_statistics <",
443 " dropped_ras: 2",
444 " duration_ms: 45000",
445 " matching_ras: 2",
446 " max_program_size: 2048",
447 " parse_errors: 2",
448 " program_updates: 4",
Hugo Benichi22d9b2d2017-02-22 13:02:27 +0900449 " program_updates_all: 7",
450 " program_updates_allowing_multicast: 3",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900451 " received_ras: 10",
Hugo Benichi4eccf782017-07-18 14:28:27 +0900452 " total_packet_dropped: 0",
453 " total_packet_processed: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900454 " zero_lifetime_ras: 1",
455 " >",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900456 ">",
457 "events <",
Hugo Benichif6840502017-03-08 11:59:36 +0900458 " if_name: \"\"",
Hugo Benichi948a8592017-03-16 16:33:47 +0900459 " link_layer: 4",
Hugo Benichif6840502017-03-08 11:59:36 +0900460 " network_id: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900461 " time_ms: 600",
Hugo Benichif6840502017-03-08 11:59:36 +0900462 " transports: 0",
Hugo Benichi00a42d42016-09-13 15:55:09 +0900463 " ra_event <",
464 " dnssl_lifetime: -1",
465 " prefix_preferred_lifetime: 300",
466 " prefix_valid_lifetime: 400",
467 " rdnss_lifetime: 1000",
468 " route_info_lifetime: -1",
469 " router_lifetime: 2000",
470 " >",
Hugo Benichid680d4c2016-10-13 13:16:16 +0900471 ">",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900472 "events <",
473 " if_name: \"\"",
Hugo Benichi380a0632017-10-20 09:25:29 +0900474 " link_layer: 5",
475 " network_id: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900476 " time_ms: 0",
477 " transports: 0",
478 " default_network_event <",
Hugo Benichi380a0632017-10-20 09:25:29 +0900479 " default_network_duration_ms: 200",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900480 " final_score: 0",
481 " initial_score: 0",
482 " ip_support: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900483 " no_default_network_duration_ms: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900484 " previous_default_network_link_layer: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900485 " previous_network_ip_support: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900486 " validation_duration_ms: 0",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900487 " >",
488 ">",
489 "events <",
490 " if_name: \"\"",
Hugo Benichi380a0632017-10-20 09:25:29 +0900491 " link_layer: 2",
492 " network_id: 100",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900493 " time_ms: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900494 " transports: 1",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900495 " default_network_event <",
Hugo Benichi380a0632017-10-20 09:25:29 +0900496 " default_network_duration_ms: 100",
497 " final_score: 50",
498 " initial_score: 50",
499 " ip_support: 2",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900500 " no_default_network_duration_ms: 0",
Hugo Benichi380a0632017-10-20 09:25:29 +0900501 " previous_default_network_link_layer: 0",
502 " previous_network_ip_support: 0",
503 " validation_duration_ms: 100",
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900504 " >",
505 ">",
506 "events <",
507 " if_name: \"\"",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900508 " link_layer: 4",
509 " network_id: 100",
510 " time_ms: 0",
511 " transports: 2",
512 " connect_statistics <",
513 " connect_blocking_count: 1",
514 " connect_count: 3",
515 " errnos_counters <",
516 " key: 11",
517 " value: 1",
518 " >",
519 " ipv6_addr_count: 1",
520 " latencies_ms: 110",
521 " >",
522 ">",
523 "events <",
524 " if_name: \"\"",
525 " link_layer: 2",
526 " network_id: 101",
527 " time_ms: 0",
528 " transports: 1",
529 " connect_statistics <",
530 " connect_blocking_count: 2",
531 " connect_count: 2",
532 " ipv6_addr_count: 1",
533 " latencies_ms: 23",
534 " latencies_ms: 45",
535 " >",
536 ">",
537 "events <",
538 " if_name: \"\"",
539 " link_layer: 4",
540 " network_id: 100",
541 " time_ms: 0",
542 " transports: 2",
543 " dns_lookup_batch <",
544 " event_types: 1",
545 " event_types: 1",
546 " event_types: 2",
Hugo Benichi4eccf782017-07-18 14:28:27 +0900547 " getaddrinfo_error_count: 0",
548 " getaddrinfo_query_count: 0",
549 " gethostbyname_error_count: 0",
550 " gethostbyname_query_count: 0",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900551 " latencies_ms: 3456",
552 " latencies_ms: 45",
553 " latencies_ms: 638",
554 " return_codes: 0",
555 " return_codes: 3",
556 " return_codes: 0",
557 " >",
558 ">",
559 "events <",
560 " if_name: \"\"",
561 " link_layer: 2",
562 " network_id: 101",
563 " time_ms: 0",
564 " transports: 1",
565 " dns_lookup_batch <",
566 " event_types: 1",
567 " event_types: 2",
Hugo Benichi4eccf782017-07-18 14:28:27 +0900568 " getaddrinfo_error_count: 0",
569 " getaddrinfo_query_count: 0",
570 " gethostbyname_error_count: 0",
571 " gethostbyname_query_count: 0",
Hugo Benichi5eb90532017-03-23 18:38:22 +0900572 " latencies_ms: 56",
573 " latencies_ms: 34",
574 " return_codes: 0",
575 " return_codes: 0",
576 " >",
577 ">",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900578 "events <",
579 " if_name: \"\"",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900580 " link_layer: 4",
581 " network_id: 0",
582 " time_ms: 0",
583 " transports: 0",
584 " wakeup_stats <",
Hugo Benichid921bce2017-10-12 21:33:40 +0900585 " application_wakeups: 3",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900586 " duration_sec: 0",
Hugo Benichid921bce2017-10-12 21:33:40 +0900587 " ethertype_counts <",
588 " key: 2048",
589 " value: 6",
590 " >",
591 " ip_next_header_counts <",
592 " key: 6",
593 " value: 3",
594 " >",
595 " ip_next_header_counts <",
596 " key: 17",
597 " value: 3",
598 " >",
599 " l2_broadcast_count: 0",
600 " l2_multicast_count: 0",
601 " l2_unicast_count: 6",
Hugo Benichi175b5742017-09-19 13:15:26 +0900602 " no_uid_wakeups: 1",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900603 " non_application_wakeups: 0",
604 " root_wakeups: 0",
605 " system_wakeups: 2",
Hugo Benichid921bce2017-10-12 21:33:40 +0900606 " total_wakeups: 6",
Hugo Benichi60c9f632017-09-05 13:34:48 +0900607 " >",
608 ">",
Hugo Benichi2a5cfb92017-03-22 22:21:44 +0900609 "version: 2\n");
Hugo Benichi00a42d42016-09-13 15:55:09 +0900610
611 verifySerialization(want, getdump("flush"));
612 }
613
614 String getdump(String ... command) {
615 StringWriter buffer = new StringWriter();
616 PrintWriter writer = new PrintWriter(buffer);
617 mService.impl.dump(null, writer, command);
618 return buffer.toString();
619 }
620
Hugo Benichi5eb90532017-03-23 18:38:22 +0900621 void connectEvent(int netid, int error, int latencyMs, String ipAddr) throws Exception {
622 mNetdListener.onConnectEvent(netid, error, latencyMs, ipAddr, 80, 1);
623 }
624
625 void dnsEvent(int netId, int type, int result, int latency) throws Exception {
626 mNetdListener.onDnsEvent(netId, type, result, latency, "", null, 0, 0);
627 }
628
Hugo Benichid921bce2017-10-12 21:33:40 +0900629 void wakeupEvent(String iface, int uid, int ether, int ip, byte[] mac, String srcIp,
630 String dstIp, int sport, int dport, long now) throws Exception {
Hugo Benichi60c9f632017-09-05 13:34:48 +0900631 String prefix = NetdEventListenerService.WAKEUP_EVENT_IFACE_PREFIX + iface;
Hugo Benichid921bce2017-10-12 21:33:40 +0900632 mNetdListener.onWakeupEvent(prefix, uid, ether, ip, mac, srcIp, dstIp, sport, dport, now);
Hugo Benichi60c9f632017-09-05 13:34:48 +0900633 }
634
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900635 NetworkAgentInfo makeNai(int netId, int score, boolean ipv4, boolean ipv6, long transports) {
636 NetworkAgentInfo nai = mock(NetworkAgentInfo.class);
637 when(nai.network()).thenReturn(new Network(netId));
638 when(nai.getCurrentScore()).thenReturn(score);
639 nai.linkProperties = new LinkProperties();
640 nai.networkCapabilities = new NetworkCapabilities();
Hugo Benichibb16b752017-12-14 09:56:04 +0900641 nai.lastValidated = true;
Hugo Benichi1193a9c2017-10-19 14:58:15 +0900642 for (int t : BitUtils.unpackBits(transports)) {
643 nai.networkCapabilities.addTransportType(t);
644 }
645 if (ipv4) {
646 nai.linkProperties.addLinkAddress(new LinkAddress("192.0.2.12/24"));
647 nai.linkProperties.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0")));
648 }
649 if (ipv6) {
650 nai.linkProperties.addLinkAddress(new LinkAddress("2001:db8:dead:beef:f00::a0/64"));
651 nai.linkProperties.addRoute(new RouteInfo(new IpPrefix("::/0")));
652 }
653 return nai;
654 }
655
Hugo Benichi00a42d42016-09-13 15:55:09 +0900656 List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
657 ArgumentCaptor<ConnectivityMetricsEvent> captor =
658 ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);
659 verify(mMockService, timeout(timeoutMs).times(n)).logEvent(captor.capture());
660 return captor.getAllValues();
661 }
662
663 List<ConnectivityMetricsEvent> verifyEvents(int n) throws Exception {
664 return verifyEvents(n, 10);
665 }
666
667 static void verifySerialization(String want, String output) {
668 try {
669 byte[] got = Base64.decode(output, Base64.DEFAULT);
670 IpConnectivityLogClass.IpConnectivityLog log =
Glen Kuhne07199402016-10-25 15:47:25 -0700671 IpConnectivityLogClass.IpConnectivityLog.parseFrom(got);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900672 assertEquals(want, log.toString());
673 } catch (Exception e) {
674 fail(e.toString());
675 }
676 }
677
678 static String joinLines(String ... elems) {
679 StringBuilder b = new StringBuilder();
680 for (String s : elems) {
681 b.append(s).append("\n");
682 }
683 return b.toString();
684 }
685
686 static ConnectivityMetricsEvent expectedEvent(int timestamp) {
Hugo Benichiec27c4d2017-03-15 15:07:42 +0900687 ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
688 ev.timestamp = timestamp;
689 ev.data = FAKE_EV;
690 return ev;
Hugo Benichi00a42d42016-09-13 15:55:09 +0900691 }
692
693 /** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */
694 static void assertEventsEqual(ConnectivityMetricsEvent expected, ConnectivityMetricsEvent got) {
695 assertEquals(expected.timestamp, got.timestamp);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900696 assertEquals(expected.data, got.data);
697 }
698
699 static final Comparator<ConnectivityMetricsEvent> EVENT_COMPARATOR =
Hugo Benichi0d4a3982016-11-25 11:24:22 +0900700 Comparator.comparingLong((ev) -> ev.timestamp);
Hugo Benichi00a42d42016-09-13 15:55:09 +0900701}