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 com.android.server.connectivity.MetricsTestUtil.aLong; 20 import static com.android.server.connectivity.MetricsTestUtil.aString; 21 import static com.android.server.connectivity.MetricsTestUtil.aType; 22 import static com.android.server.connectivity.MetricsTestUtil.anInt; 23 import static com.android.server.connectivity.MetricsTestUtil.describeIpEvent; 24 import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.BLUETOOTH; 25 import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.CELLULAR; 26 import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog; 27 import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.MULTIPLE; 28 import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.WIFI; 29 30 import static org.junit.Assert.assertEquals; 31 import static org.junit.Assert.fail; 32 33 import android.net.ConnectivityMetricsEvent; 34 import android.net.metrics.ApfProgramEvent; 35 import android.net.metrics.ApfStats; 36 import android.net.metrics.DefaultNetworkEvent; 37 import android.net.metrics.DhcpClientEvent; 38 import android.net.metrics.DhcpErrorEvent; 39 import android.net.metrics.IpManagerEvent; 40 import android.net.metrics.IpReachabilityEvent; 41 import android.net.metrics.NetworkEvent; 42 import android.net.metrics.RaEvent; 43 import android.net.metrics.ValidationProbeEvent; 44 import android.net.metrics.WakeupStats; 45 import android.test.suitebuilder.annotation.SmallTest; 46 47 import androidx.test.runner.AndroidJUnit4; 48 49 import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent; 50 51 import org.junit.Test; 52 import org.junit.runner.RunWith; 53 54 import java.util.Arrays; 55 import java.util.List; 56 57 // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto. 58 @RunWith(AndroidJUnit4.class) 59 @SmallTest 60 public class IpConnectivityEventBuilderTest { 61 62 @Test testLinkLayerInferrence()63 public void testLinkLayerInferrence() { 64 ConnectivityMetricsEvent ev = describeIpEvent( 65 aType(IpReachabilityEvent.class), 66 anInt(IpReachabilityEvent.NUD_FAILED)); 67 68 String want = String.join("\n", 69 "dropped_events: 0", 70 "events <", 71 " if_name: \"\"", 72 " link_layer: 0", 73 " network_id: 0", 74 " time_ms: 1", 75 " transports: 0", 76 " ip_reachability_event <", 77 " event_type: 512", 78 " if_name: \"\"", 79 " >", 80 ">", 81 "version: 2\n"); 82 verifySerialization(want, ev); 83 84 ev.netId = 123; 85 ev.transports = 3; // transports have priority for inferrence of link layer 86 ev.ifname = "wlan0"; 87 want = String.join("\n", 88 "dropped_events: 0", 89 "events <", 90 " if_name: \"\"", 91 String.format(" link_layer: %d", MULTIPLE), 92 " network_id: 123", 93 " time_ms: 1", 94 " transports: 3", 95 " ip_reachability_event <", 96 " event_type: 512", 97 " if_name: \"\"", 98 " >", 99 ">", 100 "version: 2\n"); 101 verifySerialization(want, ev); 102 103 ev.transports = 1; 104 ev.ifname = null; 105 want = String.join("\n", 106 "dropped_events: 0", 107 "events <", 108 " if_name: \"\"", 109 String.format(" link_layer: %d", CELLULAR), 110 " network_id: 123", 111 " time_ms: 1", 112 " transports: 1", 113 " ip_reachability_event <", 114 " event_type: 512", 115 " if_name: \"\"", 116 " >", 117 ">", 118 "version: 2\n"); 119 verifySerialization(want, ev); 120 121 ev.transports = 0; 122 ev.ifname = "not_inferred"; 123 want = String.join("\n", 124 "dropped_events: 0", 125 "events <", 126 " if_name: \"not_inferred\"", 127 " link_layer: 0", 128 " network_id: 123", 129 " time_ms: 1", 130 " transports: 0", 131 " ip_reachability_event <", 132 " event_type: 512", 133 " if_name: \"\"", 134 " >", 135 ">", 136 "version: 2\n"); 137 verifySerialization(want, ev); 138 139 ev.ifname = "bt-pan"; 140 want = String.join("\n", 141 "dropped_events: 0", 142 "events <", 143 " if_name: \"\"", 144 String.format(" link_layer: %d", BLUETOOTH), 145 " network_id: 123", 146 " time_ms: 1", 147 " transports: 0", 148 " ip_reachability_event <", 149 " event_type: 512", 150 " if_name: \"\"", 151 " >", 152 ">", 153 "version: 2\n"); 154 verifySerialization(want, ev); 155 156 ev.ifname = "rmnet_ipa0"; 157 want = String.join("\n", 158 "dropped_events: 0", 159 "events <", 160 " if_name: \"\"", 161 String.format(" link_layer: %d", CELLULAR), 162 " network_id: 123", 163 " time_ms: 1", 164 " transports: 0", 165 " ip_reachability_event <", 166 " event_type: 512", 167 " if_name: \"\"", 168 " >", 169 ">", 170 "version: 2\n"); 171 verifySerialization(want, ev); 172 173 ev.ifname = "wlan0"; 174 want = String.join("\n", 175 "dropped_events: 0", 176 "events <", 177 " if_name: \"\"", 178 String.format(" link_layer: %d", WIFI), 179 " network_id: 123", 180 " time_ms: 1", 181 " transports: 0", 182 " ip_reachability_event <", 183 " event_type: 512", 184 " if_name: \"\"", 185 " >", 186 ">", 187 "version: 2\n"); 188 verifySerialization(want, ev); 189 } 190 191 @Test testDefaultNetworkEventSerialization()192 public void testDefaultNetworkEventSerialization() { 193 DefaultNetworkEvent ev = new DefaultNetworkEvent(1001); 194 ev.netId = 102; 195 ev.transports = 2; 196 ev.previousTransports = 4; 197 ev.ipv4 = true; 198 ev.initialScore = 20; 199 ev.finalScore = 60; 200 ev.durationMs = 54; 201 ev.validatedMs = 27; 202 203 String want = String.join("\n", 204 "dropped_events: 0", 205 "events <", 206 " if_name: \"\"", 207 " link_layer: 4", 208 " network_id: 102", 209 " time_ms: 0", 210 " transports: 2", 211 " default_network_event <", 212 " default_network_duration_ms: 54", 213 " final_score: 60", 214 " initial_score: 20", 215 " ip_support: 1", 216 " no_default_network_duration_ms: 0", 217 " previous_default_network_link_layer: 1", 218 " previous_network_ip_support: 0", 219 " validation_duration_ms: 27", 220 " >", 221 ">", 222 "version: 2\n"); 223 224 verifySerialization(want, IpConnectivityEventBuilder.toProto(ev)); 225 } 226 227 @Test testDhcpClientEventSerialization()228 public void testDhcpClientEventSerialization() { 229 ConnectivityMetricsEvent ev = describeIpEvent( 230 aType(DhcpClientEvent.class), 231 aString("SomeState"), 232 anInt(192)); 233 234 String want = String.join("\n", 235 "dropped_events: 0", 236 "events <", 237 " if_name: \"\"", 238 " link_layer: 0", 239 " network_id: 0", 240 " time_ms: 1", 241 " transports: 0", 242 " dhcp_event <", 243 " duration_ms: 192", 244 " if_name: \"\"", 245 " state_transition: \"SomeState\"", 246 " >", 247 ">", 248 "version: 2\n"); 249 250 verifySerialization(want, ev); 251 } 252 253 @Test testDhcpErrorEventSerialization()254 public void testDhcpErrorEventSerialization() { 255 ConnectivityMetricsEvent ev = describeIpEvent( 256 aType(DhcpErrorEvent.class), 257 anInt(DhcpErrorEvent.L4_NOT_UDP)); 258 259 String want = String.join("\n", 260 "dropped_events: 0", 261 "events <", 262 " if_name: \"\"", 263 " link_layer: 0", 264 " network_id: 0", 265 " time_ms: 1", 266 " transports: 0", 267 " dhcp_event <", 268 " duration_ms: 0", 269 " if_name: \"\"", 270 " error_code: 50397184", 271 " >", 272 ">", 273 "version: 2\n"); 274 275 verifySerialization(want, ev); 276 } 277 278 @Test testIpManagerEventSerialization()279 public void testIpManagerEventSerialization() { 280 ConnectivityMetricsEvent ev = describeIpEvent( 281 aType(IpManagerEvent.class), 282 anInt(IpManagerEvent.PROVISIONING_OK), 283 aLong(5678)); 284 285 String want = String.join("\n", 286 "dropped_events: 0", 287 "events <", 288 " if_name: \"\"", 289 " link_layer: 0", 290 " network_id: 0", 291 " time_ms: 1", 292 " transports: 0", 293 " ip_provisioning_event <", 294 " event_type: 1", 295 " if_name: \"\"", 296 " latency_ms: 5678", 297 " >", 298 ">", 299 "version: 2\n"); 300 301 verifySerialization(want, ev); 302 } 303 304 @Test testIpReachabilityEventSerialization()305 public void testIpReachabilityEventSerialization() { 306 ConnectivityMetricsEvent ev = describeIpEvent( 307 aType(IpReachabilityEvent.class), 308 anInt(IpReachabilityEvent.NUD_FAILED)); 309 310 String want = String.join("\n", 311 "dropped_events: 0", 312 "events <", 313 " if_name: \"\"", 314 " link_layer: 0", 315 " network_id: 0", 316 " time_ms: 1", 317 " transports: 0", 318 " ip_reachability_event <", 319 " event_type: 512", 320 " if_name: \"\"", 321 " >", 322 ">", 323 "version: 2\n"); 324 325 verifySerialization(want, ev); 326 } 327 328 @Test testNetworkEventSerialization()329 public void testNetworkEventSerialization() { 330 ConnectivityMetricsEvent ev = describeIpEvent( 331 aType(NetworkEvent.class), 332 anInt(5), 333 aLong(20410)); 334 335 String want = String.join("\n", 336 "dropped_events: 0", 337 "events <", 338 " if_name: \"\"", 339 " link_layer: 0", 340 " network_id: 0", 341 " time_ms: 1", 342 " transports: 0", 343 " network_event <", 344 " event_type: 5", 345 " latency_ms: 20410", 346 " >", 347 ">", 348 "version: 2\n"); 349 350 verifySerialization(want, ev); 351 } 352 353 @Test testValidationProbeEventSerialization()354 public void testValidationProbeEventSerialization() { 355 ConnectivityMetricsEvent ev = describeIpEvent( 356 aType(ValidationProbeEvent.class), 357 aLong(40730), 358 anInt(ValidationProbeEvent.PROBE_HTTP), 359 anInt(204)); 360 361 String want = String.join("\n", 362 "dropped_events: 0", 363 "events <", 364 " if_name: \"\"", 365 " link_layer: 0", 366 " network_id: 0", 367 " time_ms: 1", 368 " transports: 0", 369 " validation_probe_event <", 370 " latency_ms: 40730", 371 " probe_result: 204", 372 " probe_type: 1", 373 " >", 374 ">", 375 "version: 2\n"); 376 377 verifySerialization(want, ev); 378 } 379 380 @Test testApfProgramEventSerialization()381 public void testApfProgramEventSerialization() { 382 ConnectivityMetricsEvent ev = describeIpEvent( 383 aType(ApfProgramEvent.class), 384 aLong(200), 385 aLong(18), 386 anInt(7), 387 anInt(9), 388 anInt(2048), 389 anInt(3)); 390 391 String want = String.join("\n", 392 "dropped_events: 0", 393 "events <", 394 " if_name: \"\"", 395 " link_layer: 0", 396 " network_id: 0", 397 " time_ms: 1", 398 " transports: 0", 399 " apf_program_event <", 400 " current_ras: 9", 401 " drop_multicast: true", 402 " effective_lifetime: 18", 403 " filtered_ras: 7", 404 " has_ipv4_addr: true", 405 " lifetime: 200", 406 " program_length: 2048", 407 " >", 408 ">", 409 "version: 2\n"); 410 411 verifySerialization(want, ev); 412 } 413 414 @Test testApfStatsSerialization()415 public void testApfStatsSerialization() { 416 ConnectivityMetricsEvent ev = describeIpEvent( 417 aType(ApfStats.class), 418 aLong(45000), 419 anInt(10), 420 anInt(2), 421 anInt(2), 422 anInt(1), 423 anInt(2), 424 anInt(4), 425 anInt(7), 426 anInt(3), 427 anInt(2048)); 428 429 String want = String.join("\n", 430 "dropped_events: 0", 431 "events <", 432 " if_name: \"\"", 433 " link_layer: 0", 434 " network_id: 0", 435 " time_ms: 1", 436 " transports: 0", 437 " apf_statistics <", 438 " dropped_ras: 2", 439 " duration_ms: 45000", 440 " matching_ras: 2", 441 " max_program_size: 2048", 442 " parse_errors: 2", 443 " program_updates: 4", 444 " program_updates_all: 7", 445 " program_updates_allowing_multicast: 3", 446 " received_ras: 10", 447 " total_packet_dropped: 0", 448 " total_packet_processed: 0", 449 " zero_lifetime_ras: 1", 450 " >", 451 ">", 452 "version: 2\n"); 453 454 verifySerialization(want, ev); 455 } 456 457 @Test testRaEventSerialization()458 public void testRaEventSerialization() { 459 ConnectivityMetricsEvent ev = describeIpEvent( 460 aType(RaEvent.class), 461 aLong(2000), 462 aLong(400), 463 aLong(300), 464 aLong(-1), 465 aLong(1000), 466 aLong(-1)); 467 468 String want = String.join("\n", 469 "dropped_events: 0", 470 "events <", 471 " if_name: \"\"", 472 " link_layer: 0", 473 " network_id: 0", 474 " time_ms: 1", 475 " transports: 0", 476 " ra_event <", 477 " dnssl_lifetime: -1", 478 " prefix_preferred_lifetime: 300", 479 " prefix_valid_lifetime: 400", 480 " rdnss_lifetime: 1000", 481 " route_info_lifetime: -1", 482 " router_lifetime: 2000", 483 " >", 484 ">", 485 "version: 2\n"); 486 487 verifySerialization(want, ev); 488 } 489 490 @Test testWakeupStatsSerialization()491 public void testWakeupStatsSerialization() { 492 WakeupStats stats = new WakeupStats("wlan0"); 493 stats.totalWakeups = 14; 494 stats.applicationWakeups = 5; 495 stats.nonApplicationWakeups = 1; 496 stats.rootWakeups = 2; 497 stats.systemWakeups = 3; 498 stats.noUidWakeups = 3; 499 stats.l2UnicastCount = 5; 500 stats.l2MulticastCount = 1; 501 stats.l2BroadcastCount = 2; 502 stats.ethertypes.put(0x800, 3); 503 stats.ethertypes.put(0x86dd, 3); 504 stats.ipNextHeaders.put(6, 5); 505 506 507 IpConnectivityEvent got = IpConnectivityEventBuilder.toProto(stats); 508 String want = String.join("\n", 509 "dropped_events: 0", 510 "events <", 511 " if_name: \"\"", 512 " link_layer: 4", 513 " network_id: 0", 514 " time_ms: 0", 515 " transports: 0", 516 " wakeup_stats <", 517 " application_wakeups: 5", 518 " duration_sec: 0", 519 " ethertype_counts <", 520 " key: 2048", 521 " value: 3", 522 " >", 523 " ethertype_counts <", 524 " key: 34525", 525 " value: 3", 526 " >", 527 " ip_next_header_counts <", 528 " key: 6", 529 " value: 5", 530 " >", 531 " l2_broadcast_count: 2", 532 " l2_multicast_count: 1", 533 " l2_unicast_count: 5", 534 " no_uid_wakeups: 3", 535 " non_application_wakeups: 1", 536 " root_wakeups: 2", 537 " system_wakeups: 3", 538 " total_wakeups: 14", 539 " >", 540 ">", 541 "version: 2\n"); 542 543 verifySerialization(want, got); 544 } 545 verifySerialization(String want, ConnectivityMetricsEvent... input)546 static void verifySerialization(String want, ConnectivityMetricsEvent... input) { 547 List<IpConnectivityEvent> protoInput = 548 IpConnectivityEventBuilder.toProto(Arrays.asList(input)); 549 verifySerialization(want, protoInput.toArray(new IpConnectivityEvent[0])); 550 } 551 verifySerialization(String want, IpConnectivityEvent... input)552 static void verifySerialization(String want, IpConnectivityEvent... input) { 553 try { 554 byte[] got = IpConnectivityEventBuilder.serialize(0, Arrays.asList(input)); 555 IpConnectivityLog log = IpConnectivityLog.parseFrom(got); 556 assertEquals(want, log.toString()); 557 } catch (Exception e) { 558 fail(e.toString()); 559 } 560 } 561 } 562