diff --git a/transport/transport-backend-cct/src/main/java/com/google/android/datatransport/cct/CctTransportBackend.java b/transport/transport-backend-cct/src/main/java/com/google/android/datatransport/cct/CctTransportBackend.java index c387a34a9ef..8c1ae0ae10b 100644 --- a/transport/transport-backend-cct/src/main/java/com/google/android/datatransport/cct/CctTransportBackend.java +++ b/transport/transport-backend-cct/src/main/java/com/google/android/datatransport/cct/CctTransportBackend.java @@ -27,6 +27,7 @@ import com.google.android.datatransport.cct.proto.LogResponse; import com.google.android.datatransport.cct.proto.NetworkConnectionInfo; import com.google.android.datatransport.cct.proto.NetworkConnectionInfo.MobileSubtype; +import com.google.android.datatransport.cct.proto.NetworkConnectionInfo.NetworkType; import com.google.android.datatransport.cct.proto.QosTierConfiguration; import com.google.android.datatransport.runtime.EventInternal; import com.google.android.datatransport.runtime.backends.BackendRequest; @@ -65,6 +66,9 @@ final class CctTransportBackend implements TransportBackend { private static final String CONTENT_TYPE_HEADER_KEY = "Content-Type"; private static final String PROTOBUF_CONTENT_TYPE = "application/x-protobuf"; + @VisibleForTesting static final String KEY_NETWORK_TYPE = "net-type"; + @VisibleForTesting static final String KEY_MOBILE_SUBTYPE = "mobile-subtype"; + private static final String KEY_SDK_VERSION = "sdk-version"; private static final String KEY_MODEL = "model"; private static final String KEY_HARDWARE = "hardware"; @@ -73,8 +77,6 @@ final class CctTransportBackend implements TransportBackend { private static final String KEY_OS_BUILD = "os-uild"; private static final String KEY_MANUFACTURER = "manufacturer"; private static final String KEY_FINGERPRINT = "fingerprint"; - private static final String KEY_NETWORK_TYPE = "net-type"; - private static final String KEY_MOBILE_SUBTYPE = "mobile-subtype"; private static final String KEY_TIMEZONE_OFFSET = "tz-offset"; private final ConnectivityManager connectivityManager; @@ -125,12 +127,25 @@ public EventInternal decorate(EventInternal eventInternal) { .addMetadata(KEY_MANUFACTURER, Build.MANUFACTURER) .addMetadata(KEY_FINGERPRINT, Build.FINGERPRINT) .addMetadata(KEY_TIMEZONE_OFFSET, getTzOffset()) - .addMetadata(KEY_NETWORK_TYPE, networkInfo.getType()) - .addMetadata(KEY_MOBILE_SUBTYPE, toSubtypeValue(networkInfo.getSubtype())) + .addMetadata(KEY_NETWORK_TYPE, getNetTypeValue(networkInfo)) + .addMetadata(KEY_MOBILE_SUBTYPE, getNetSubtypeValue(networkInfo)) .build(); } - private int toSubtypeValue(int subtype) { + private static int getNetTypeValue(NetworkInfo networkInfo) { + // when the device is not connected networkInfo returned by ConnectivityManger is null. + if (networkInfo == null) { + return NetworkType.NONE_VALUE; + } + return networkInfo.getType(); + } + + private static int getNetSubtypeValue(NetworkInfo networkInfo) { + // when the device is not connected networkInfo returned by ConnectivityManger is null. + if (networkInfo == null) { + return MobileSubtype.UNKNOWN_MOBILE_SUBTYPE_VALUE; + } + int subtype = networkInfo.getSubtype(); if (subtype == -1) { return MobileSubtype.COMBINED_VALUE; } diff --git a/transport/transport-backend-cct/src/test/java/com/google/android/datatransport/cct/CctTransportBackendTest.java b/transport/transport-backend-cct/src/test/java/com/google/android/datatransport/cct/CctTransportBackendTest.java index b0d3b5f8d4f..4e307617674 100644 --- a/transport/transport-backend-cct/src/test/java/com/google/android/datatransport/cct/CctTransportBackendTest.java +++ b/transport/transport-backend-cct/src/test/java/com/google/android/datatransport/cct/CctTransportBackendTest.java @@ -23,6 +23,7 @@ import static com.github.tomakehurst.wiremock.client.WireMock.verify; import static com.google.android.datatransport.cct.CctTransportBackend.getTzOffset; import static com.google.android.datatransport.cct.ProtoMatchers.protoMatcher; +import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import android.content.Context; @@ -47,6 +48,9 @@ import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; @RunWith(RobolectricTestRunner.class) public class CctTransportBackendTest { @@ -205,4 +209,59 @@ public void send_whenBackendResponseTimesOut_shouldReturnTransientError() { assertEquals(response, BackendResponse.transientError()); } + + @Test + public void decorate_whenOnline_shouldProperlyPopulateNetworkInfo() { + CctTransportBackend backend = + new CctTransportBackend( + RuntimeEnvironment.application, TEST_ENDPOINT, wallClock, uptimeClock, 300); + + EventInternal result = + backend.decorate( + EventInternal.builder() + .setEventMillis(INITIAL_WALL_TIME) + .setUptimeMillis(INITIAL_UPTIME) + .setTransportName("3") + .setPayload(PAYLOAD.toByteArray()) + .build()); + + assertThat(result.get(CctTransportBackend.KEY_NETWORK_TYPE)) + .isEqualTo(String.valueOf(NetworkConnectionInfo.NetworkType.MOBILE_VALUE)); + assertThat(result.get(CctTransportBackend.KEY_MOBILE_SUBTYPE)) + .isEqualTo(String.valueOf(NetworkConnectionInfo.MobileSubtype.EDGE_VALUE)); + } + + @Test + @Config(shadows = {OfflineConnectivityManagerShadow.class}) + public void decorate_whenOffline_shouldProperlyPopulateNetworkInfo() { + CctTransportBackend backend = + new CctTransportBackend( + RuntimeEnvironment.application, TEST_ENDPOINT, wallClock, uptimeClock, 300); + + EventInternal result = + backend.decorate( + EventInternal.builder() + .setEventMillis(INITIAL_WALL_TIME) + .setUptimeMillis(INITIAL_UPTIME) + .setTransportName("3") + .setPayload(PAYLOAD.toByteArray()) + .build()); + + assertThat(result.get(CctTransportBackend.KEY_NETWORK_TYPE)) + .isEqualTo(String.valueOf(NetworkConnectionInfo.NetworkType.NONE_VALUE)); + assertThat(result.get(CctTransportBackend.KEY_MOBILE_SUBTYPE)) + .isEqualTo( + String.valueOf(NetworkConnectionInfo.MobileSubtype.UNKNOWN_MOBILE_SUBTYPE_VALUE)); + } + + // When there is no active network, the ConnectivityManager returns null when + // getActiveNetworkInfo() is called. + @Implements(ConnectivityManager.class) + public static class OfflineConnectivityManagerShadow { + + @Implementation + public NetworkInfo getActiveNetworkInfo() { + return null; + } + } }