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