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