From a54812907b70b0a2f7ac37a6d63c04ddaecd26f3 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Fri, 2 Sep 2016 09:00:59 +0900 Subject: [PATCH] Add ipconnectivity.proto to services jar This patch moves ipconnectivity.proto and companion serialization classes from /vendor/google/app/ConnectivityMetrics into the framework services jar. This will allow to implement a dumpsys interface for IpConnectivity metrics events defined in android.net.metrics that output metrics as a serialized proto. Bug: 31254800 Change-Id: Ia4449103fd7222c9d899352fea2dce47a790a49c --- .../IpConnectivityEventBuilderTest.java | 359 ++++++++++++++++++ .../server/connectivity/MetricsTestUtil.java | 120 ++++++ 2 files changed, 479 insertions(+) create mode 100644 services/tests/servicestests/src/com/android/server/connectivity/IpConnectivityEventBuilderTest.java create mode 100644 services/tests/servicestests/src/com/android/server/connectivity/MetricsTestUtil.java diff --git a/services/tests/servicestests/src/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/services/tests/servicestests/src/com/android/server/connectivity/IpConnectivityEventBuilderTest.java new file mode 100644 index 0000000000..aed3635245 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/connectivity/IpConnectivityEventBuilderTest.java @@ -0,0 +1,359 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.connectivity; + +import android.net.ConnectivityMetricsEvent; +import android.net.metrics.ApfProgramEvent; +import android.net.metrics.ApfStats; +import android.net.metrics.DefaultNetworkEvent; +import android.net.metrics.DhcpClientEvent; +import android.net.metrics.DhcpErrorEvent; +import android.net.metrics.DnsEvent; +import android.net.metrics.IpManagerEvent; +import android.net.metrics.IpReachabilityEvent; +import android.net.metrics.NetworkEvent; +import android.net.metrics.RaEvent; +import android.net.metrics.ValidationProbeEvent; +import com.google.protobuf.nano.MessageNano; +import java.util.Arrays; +import junit.framework.TestCase; + +import static com.android.server.connectivity.metrics.IpConnectivityLogClass.IpConnectivityLog; +import static com.android.server.connectivity.MetricsTestUtil.aBool; +import static com.android.server.connectivity.MetricsTestUtil.aByteArray; +import static com.android.server.connectivity.MetricsTestUtil.aLong; +import static com.android.server.connectivity.MetricsTestUtil.aString; +import static com.android.server.connectivity.MetricsTestUtil.aType; +import static com.android.server.connectivity.MetricsTestUtil.anInt; +import static com.android.server.connectivity.MetricsTestUtil.anIntArray; +import static com.android.server.connectivity.MetricsTestUtil.b; +import static com.android.server.connectivity.MetricsTestUtil.describeIpEvent; +import static com.android.server.connectivity.MetricsTestUtil.ipEv; + +public class IpConnectivityEventBuilderTest extends TestCase { + + public void testDefaultNetworkEventSerialization() { + ConnectivityMetricsEvent ev = describeIpEvent( + aType(DefaultNetworkEvent.class), + anInt(102), + anIntArray(1, 2, 3), + anInt(101), + aBool(true), + aBool(false)); + + String want = joinLines( + "dropped_events: 0", + "events <", + " default_network_event <", + " network_id <", + " network_id: 102", + " >", + " previous_network_id <", + " network_id: 101", + " >", + " previous_network_ip_support: 1", + " transport_types: 1", + " transport_types: 2", + " transport_types: 3", + " >", + " time_ms: 1", + ">"); + + verifySerialization(want, ev); + } + + public void testDhcpClientEventSerialization() { + ConnectivityMetricsEvent ev = describeIpEvent( + aType(DhcpClientEvent.class), + aString("wlan0"), + aString("SomeState"), + anInt(192)); + + String want = joinLines( + "dropped_events: 0", + "events <", + " dhcp_event <", + " duration_ms: 192", + " error_code: 0", + " if_name: \"wlan0\"", + " state_transition: \"SomeState\"", + " >", + " time_ms: 1", + ">"); + + verifySerialization(want, ev); + } + + public void testDhcpErrorEventSerialization() { + ConnectivityMetricsEvent ev = describeIpEvent( + aType(DhcpErrorEvent.class), + aString("wlan0"), + anInt(DhcpErrorEvent.L4_NOT_UDP)); + + String want = joinLines( + "dropped_events: 0", + "events <", + " dhcp_event <", + " duration_ms: 0", + " error_code: 50397184", + " if_name: \"wlan0\"", + " state_transition: \"\"", + " >", + " time_ms: 1", + ">"); + + verifySerialization(want, ev); + } + + public void testDnsEventSerialization() { + ConnectivityMetricsEvent ev = describeIpEvent( + aType(DnsEvent.class), + anInt(101), + aByteArray(b(1), b(1), b(2), b(1), b(1), b(1), b(2), b(2)), + aByteArray(b(0), b(0), b(22), b(3), b(1), b(0), b(200), b(178)), + anIntArray(3456, 267, 1230, 45, 2111, 450, 638, 1300)); + + String want = joinLines( + "dropped_events: 0", + "events <", + " dns_lookup_batch <", + " event_types: 1", + " event_types: 1", + " event_types: 2", + " event_types: 1", + " event_types: 1", + " event_types: 1", + " event_types: 2", + " event_types: 2", + " latencies_ms: 3456", + " latencies_ms: 267", + " latencies_ms: 1230", + " latencies_ms: 45", + " latencies_ms: 2111", + " latencies_ms: 450", + " latencies_ms: 638", + " latencies_ms: 1300", + " network_id <", + " network_id: 101", + " >", + " return_codes: 0", + " return_codes: 0", + " return_codes: 22", + " return_codes: 3", + " return_codes: 1", + " return_codes: 0", + " return_codes: 200", + " return_codes: 178", + " >", + " time_ms: 1", + ">"); + + verifySerialization(want, ev); + } + + public void testIpManagerEventSerialization() { + ConnectivityMetricsEvent ev = describeIpEvent( + aType(IpManagerEvent.class), + aString("wlan0"), + anInt(IpManagerEvent.PROVISIONING_OK), + aLong(5678)); + + String want = joinLines( + "dropped_events: 0", + "events <", + " ip_provisioning_event <", + " event_type: 1", + " if_name: \"wlan0\"", + " latency_ms: 5678", + " >", + " time_ms: 1", + ">"); + + verifySerialization(want, ev); + } + + public void testIpReachabilityEventSerialization() { + ConnectivityMetricsEvent ev = describeIpEvent( + aType(IpReachabilityEvent.class), + aString("wlan0"), + anInt(IpReachabilityEvent.NUD_FAILED)); + + String want = joinLines( + "dropped_events: 0", + "events <", + " ip_reachability_event <", + " event_type: 512", + " if_name: \"wlan0\"", + " >", + " time_ms: 1", + ">"); + + verifySerialization(want, ev); + } + + public void testNetworkEventSerialization() { + ConnectivityMetricsEvent ev = describeIpEvent( + aType(NetworkEvent.class), + anInt(100), + anInt(5), + aLong(20410)); + + String want = joinLines( + "dropped_events: 0", + "events <", + " network_event <", + " event_type: 5", + " latency_ms: 20410", + " network_id <", + " network_id: 100", + " >", + " >", + " time_ms: 1", + ">"); + + verifySerialization(want, ev); + } + + public void testValidationProbeEventSerialization() { + ConnectivityMetricsEvent ev = describeIpEvent( + aType(ValidationProbeEvent.class), + anInt(120), + aLong(40730), + anInt(ValidationProbeEvent.PROBE_HTTP), + anInt(204)); + + String want = joinLines( + "dropped_events: 0", + "events <", + " time_ms: 1", + " validation_probe_event <", + " latency_ms: 40730", + " network_id <", + " network_id: 120", + " >", + " probe_result: 204", + " probe_type: 1", + " >", + ">"); + + verifySerialization(want, ev); + } + + public void testApfProgramEventSerialization() { + ConnectivityMetricsEvent ev = describeIpEvent( + aType(ApfProgramEvent.class), + aLong(200), + anInt(7), + anInt(9), + anInt(2048), + anInt(3)); + + String want = joinLines( + "dropped_events: 0", + "events <", + " apf_program_event <", + " current_ras: 9", + " drop_multicast: true", + " filtered_ras: 7", + " has_ipv4_addr: true", + " lifetime: 200", + " program_length: 2048", + " >", + " time_ms: 1", + ">"); + + verifySerialization(want, ev); + } + + public void testApfStatsSerialization() { + ConnectivityMetricsEvent ev = describeIpEvent( + aType(ApfStats.class), + aLong(45000), + anInt(10), + anInt(2), + anInt(2), + anInt(1), + anInt(2), + anInt(4), + anInt(2048)); + + String want = joinLines( + "dropped_events: 0", + "events <", + " apf_statistics <", + " dropped_ras: 2", + " duration_ms: 45000", + " matching_ras: 2", + " max_program_size: 2048", + " parse_errors: 2", + " program_updates: 4", + " received_ras: 10", + " zero_lifetime_ras: 1", + " >", + " time_ms: 1", + ">"); + + verifySerialization(want, ev); + } + + public void testRaEventSerialization() { + ConnectivityMetricsEvent ev = describeIpEvent( + aType(RaEvent.class), + aLong(2000), + aLong(400), + aLong(300), + aLong(-1), + aLong(1000), + aLong(-1)); + + String want = joinLines( + "dropped_events: 0", + "events <", + " ra_event <", + " dnssl_lifetime: -1", + " prefix_preferred_lifetime: 300", + " prefix_valid_lifetime: 400", + " rdnss_lifetime: 1000", + " route_info_lifetime: -1", + " router_lifetime: 2000", + " >", + " time_ms: 1", + ">"); + + verifySerialization(want, ev); + } + + static void verifySerialization(String want, ConnectivityMetricsEvent... input) { + try { + byte[] got = IpConnectivityEventBuilder.serialize(0, Arrays.asList(input)); + IpConnectivityLog log = new IpConnectivityLog(); + MessageNano.mergeFrom(log, got); + assertEquals(want, log.toString()); + } catch (Exception e) { + fail(e.toString()); + } + } + + static String joinLines(String ... elems) { + StringBuilder b = new StringBuilder(); + for (String s : elems) { + b.append(s); + b.append("\n"); + } + return b.toString(); + } +} diff --git a/services/tests/servicestests/src/com/android/server/connectivity/MetricsTestUtil.java b/services/tests/servicestests/src/com/android/server/connectivity/MetricsTestUtil.java new file mode 100644 index 0000000000..e201012781 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/connectivity/MetricsTestUtil.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.connectivity; + +import android.net.ConnectivityMetricsEvent; +import android.net.ConnectivityMetricsLogger; +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; + +abstract public class MetricsTestUtil { + private MetricsTestUtil() { + } + + static ConnectivityMetricsEvent ipEv(Parcelable p) { + return ev(ConnectivityMetricsLogger.COMPONENT_TAG_CONNECTIVITY, p); + } + + static ConnectivityMetricsEvent telephonyEv() { + return ev(ConnectivityMetricsLogger.COMPONENT_TAG_TELEPHONY, new Bundle()); + } + + static ConnectivityMetricsEvent ev(int tag, Parcelable p) { + return new ConnectivityMetricsEvent(1L, tag, 0, p); + } + + // Utiliy interface for describing the content of a Parcel. This relies on + // the implementation defails of Parcelable and on the fact that the fully + // qualified Parcelable class names are written as string in the Parcels. + interface ParcelField { + void write(Parcel p); + } + + static ConnectivityMetricsEvent describeIpEvent(ParcelField... fs) { + Parcel p = Parcel.obtain(); + for (ParcelField f : fs) { + f.write(p); + } + p.setDataPosition(0); + return ipEv(p.readParcelable(ClassLoader.getSystemClassLoader())); + } + + static ParcelField aType(Class c) { + return new ParcelField() { + public void write(Parcel p) { + p.writeString(c.getName()); + } + }; + } + + static ParcelField aBool(boolean b) { + return aByte((byte) (b ? 1 : 0)); + } + + static ParcelField aByte(byte b) { + return new ParcelField() { + public void write(Parcel p) { + p.writeByte(b); + } + }; + } + + static ParcelField anInt(int i) { + return new ParcelField() { + public void write(Parcel p) { + p.writeInt(i); + } + }; + } + + static ParcelField aLong(long l) { + return new ParcelField() { + public void write(Parcel p) { + p.writeLong(l); + } + }; + } + + static ParcelField aString(String s) { + return new ParcelField() { + public void write(Parcel p) { + p.writeString(s); + } + }; + } + + static ParcelField aByteArray(byte... ary) { + return new ParcelField() { + public void write(Parcel p) { + p.writeByteArray(ary); + } + }; + } + + static ParcelField anIntArray(int... ary) { + return new ParcelField() { + public void write(Parcel p) { + p.writeIntArray(ary); + } + }; + } + + static byte b(int i) { + return (byte) i; + } +}