Merge "[Provider Model] Update internet preference icon and summary"
diff --git a/res/drawable/ic_settings_ethernet.xml b/res/drawable/ic_settings_ethernet.xml
new file mode 100644
index 0000000..6546b9a
--- /dev/null
+++ b/res/drawable/ic_settings_ethernet.xml
@@ -0,0 +1,34 @@
+ <!--
+  ~ Copyright (C) 2021 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.
+  -->
+ <vector xmlns:android="http://schemas.android.com/apk/res/android"
+         android:width="24dp"
+         android:height="24dp"
+         android:viewportWidth="24"
+         android:viewportHeight="24"
+         android:tint="?attr/colorControlNormal">
+     <path
+         android:fillColor="@android:color/white"
+         android:pathData="M17,6l-1.41,1.41L20.17,12l-4.58,4.59L17,18l6,-6zM8.41,7.41L7,6l-6,6 6,6 1.41,-1.41L3.83,12z"/>
+     <path
+         android:fillColor="@android:color/white"
+         android:pathData="M8,12m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"/>
+     <path
+         android:fillColor="@android:color/white"
+         android:pathData="M12,12m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"/>
+     <path
+         android:fillColor="@android:color/white"
+         android:pathData="M16,12m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"/>
+ </vector>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 114b41c..bcae9a5 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -12550,6 +12550,10 @@
     <string name="resetting_internet_text">Resetting your internet\u2026</string>
     <!-- Menu option for data connectivity recovery for all requested technologies. [CHAR_LIMIT=NONE] -->
     <string name="fix_connectivity">Fix connectivity</string>
+    <!-- Summary for airplane mode networks available. [CHAR LIMIT=60] -->
+    <string name="airplane_mode_network_available">Airplane mode networks available</string>
+    <!-- Summary for warning to disconnect ethernet first then switch to other networks. [CHAR LIMIT=60] -->
+    <string name="to_switch_networks_disconnect_ethernet">To switch networks, disconnect ethernet</string>
 
     <!-- Summary text separator for preferences including a short description
          (eg. "Connected / 5G"). [CHAR LIMIT=50] -->
diff --git a/src/com/android/settings/network/InternetPreferenceController.java b/src/com/android/settings/network/InternetPreferenceController.java
index 3cdcaca..790ca00 100644
--- a/src/com/android/settings/network/InternetPreferenceController.java
+++ b/src/com/android/settings/network/InternetPreferenceController.java
@@ -16,41 +16,107 @@
 
 package com.android.settings.network;
 
-import android.content.Context;
+import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
+import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
 
+import static com.android.settings.network.InternetUpdater.INTERNET_APM;
+import static com.android.settings.network.InternetUpdater.INTERNET_APM_NETWORKS;
+import static com.android.settings.network.InternetUpdater.INTERNET_CELLULAR;
+import static com.android.settings.network.InternetUpdater.INTERNET_ETHERNET;
+import static com.android.settings.network.InternetUpdater.INTERNET_WIFI;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+
+import androidx.annotation.IdRes;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
-import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.R;
 import com.android.settings.widget.SummaryUpdater;
 import com.android.settings.wifi.WifiSummaryUpdater;
+import com.android.settingslib.Utils;
 import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnPause;
-import com.android.settingslib.core.lifecycle.events.OnResume;
+
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * PreferenceController to update the internet state.
  */
 public class InternetPreferenceController extends AbstractPreferenceController implements
-        PreferenceControllerMixin, SummaryUpdater.OnSummaryChangeListener,
-        LifecycleObserver, OnResume, OnPause {
+        LifecycleObserver, SummaryUpdater.OnSummaryChangeListener,
+        InternetUpdater.OnInternetTypeChangedListener {
 
-    public static final String KEY_INTERNET_SETTINGS = "internet_settings";
+    public static final String KEY = "internet_settings";
 
     private Preference mPreference;
     private final WifiSummaryUpdater mSummaryHelper;
+    private InternetUpdater mInternetUpdater;
+    private @InternetUpdater.InternetType int mInternetType;
 
-    public InternetPreferenceController(Context context) {
+    private static Map<Integer, Integer> sIconMap = new HashMap<>();
+    static {
+        sIconMap.put(INTERNET_APM, R.drawable.ic_airplanemode_active);
+        sIconMap.put(INTERNET_APM_NETWORKS, R.drawable.ic_airplane_safe_networks_24dp);
+        sIconMap.put(INTERNET_WIFI, R.drawable.ic_wifi_signal_4);
+        sIconMap.put(INTERNET_CELLULAR, R.drawable.ic_network_cell);
+        sIconMap.put(INTERNET_ETHERNET, R.drawable.ic_settings_ethernet);
+    }
+
+    private static Map<Integer, Integer> sSummaryMap = new HashMap<>();
+    static {
+        sSummaryMap.put(INTERNET_APM, R.string.condition_airplane_title);
+        sSummaryMap.put(INTERNET_APM_NETWORKS, R.string.airplane_mode_network_available);
+        sSummaryMap.put(INTERNET_WIFI, 0);
+        sSummaryMap.put(INTERNET_CELLULAR, 0);
+        sSummaryMap.put(INTERNET_ETHERNET, R.string.to_switch_networks_disconnect_ethernet);
+    }
+
+    public InternetPreferenceController(Context context, Lifecycle lifecycle) {
         super(context);
+        if (lifecycle == null) {
+            throw new IllegalArgumentException("Lifecycle must be set");
+        }
         mSummaryHelper = new WifiSummaryUpdater(mContext, this);
+        mInternetUpdater = new InternetUpdater(context, lifecycle, this);
+        mInternetType = mInternetUpdater.getInternetType();
+        lifecycle.addObserver(this);
     }
 
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
-        mPreference = screen.findPreference(KEY_INTERNET_SETTINGS);
+        mPreference = screen.findPreference(KEY);
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        if (mPreference == null) {
+            return;
+        }
+        final @IdRes int icon = sIconMap.get(mInternetType);
+        if (icon != 0) {
+            final Drawable drawable = mContext.getDrawable(icon);
+            if (drawable != null) {
+                drawable.setTintList(
+                        Utils.getColorAttr(mContext, android.R.attr.colorControlNormal));
+                mPreference.setIcon(drawable);
+            }
+        }
+        if (mInternetType == INTERNET_CELLULAR) {
+            updateCellularSummary();
+            return;
+        }
+        final @IdRes int summary = sSummaryMap.get(mInternetType);
+        if (summary != 0) {
+            mPreference.setSummary(summary);
+        }
     }
 
     @Override
@@ -60,23 +126,45 @@
 
     @Override
     public String getPreferenceKey() {
-        return KEY_INTERNET_SETTINGS;
+        return KEY;
     }
 
-    @Override
+    /** @OnLifecycleEvent(ON_RESUME) */
+    @OnLifecycleEvent(ON_RESUME)
     public void onResume() {
         mSummaryHelper.register(true);
     }
 
-    @Override
+    /** @OnLifecycleEvent(ON_PAUSE) */
+    @OnLifecycleEvent(ON_PAUSE)
     public void onPause() {
         mSummaryHelper.register(false);
     }
 
+    /**
+     * Called when internet type is changed.
+     *
+     * @param internetType the internet type
+     */
+    public void onInternetTypeChanged(@InternetUpdater.InternetType int internetType) {
+        mInternetType = internetType;
+        updateState(mPreference);
+    }
+
     @Override
     public void onSummaryChanged(String summary) {
-        if (mPreference != null) {
+        if (mPreference != null && mInternetType == INTERNET_WIFI) {
             mPreference.setSummary(summary);
         }
     }
+
+    private void updateCellularSummary() {
+        final SubscriptionManager subscriptionManager =
+                mContext.getSystemService(SubscriptionManager.class);
+        if (subscriptionManager == null) {
+            return;
+        }
+        SubscriptionInfo subInfo = subscriptionManager.getDefaultDataSubscriptionInfo();
+        mPreference.setSummary(subInfo.getDisplayName());
+    }
 }
diff --git a/src/com/android/settings/network/InternetUpdater.java b/src/com/android/settings/network/InternetUpdater.java
new file mode 100644
index 0000000..1eafb60
--- /dev/null
+++ b/src/com/android/settings/network/InternetUpdater.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2021 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.settings.network;
+
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+
+import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
+import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
+
+import android.annotation.NonNull;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkCapabilities.Transport;
+import android.net.wifi.WifiManager;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
+
+import com.android.settings.AirplaneModeEnabler;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Helper class to update the internet type for connected network preference
+ */
+public class InternetUpdater implements AirplaneModeEnabler.OnAirplaneModeChangedListener,
+        LifecycleObserver {
+
+    private static final String TAG = "InternetUpdater";
+
+    private OnInternetTypeChangedListener mOnInternetTypeChangedListener;
+
+    /** Interface that handles the internet type changed callback */
+    public interface OnInternetTypeChangedListener {
+        /**
+         * Called when internet type is changed.
+         *
+         * @param internetType the internet type
+         */
+        void onInternetTypeChanged(@InternetType int internetType);
+    }
+
+    /**
+     * Indicates this internet is unavailable type in airplane mode on.
+     */
+    public static final int INTERNET_APM = 0;
+
+    /**
+     * Indicates this internet uses an airplane mode network type.
+     */
+    public static final int INTERNET_APM_NETWORKS = 1;
+
+    /**
+     * Indicates this internet uses a Wi-Fi network type.
+     */
+    public static final int INTERNET_WIFI = 2;
+
+    /**
+     * Indicates this internet uses a Cellular network type.
+     */
+    public static final int INTERNET_CELLULAR = 3;
+
+    /**
+     * Indicates this internet uses a Ethernet network type.
+     */
+    public static final int INTERNET_ETHERNET = 4;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @android.annotation.IntDef(prefix = { "INTERNET_" }, value = {
+            INTERNET_APM,
+            INTERNET_APM_NETWORKS,
+            INTERNET_WIFI,
+            INTERNET_CELLULAR,
+            INTERNET_ETHERNET,
+    })
+    public @interface InternetType { }
+    private @InternetType int mInternetType;
+
+    private final Context mContext;
+    private final ConnectivityManager mConnectivityManager;
+    private final WifiManager mWifiManager;
+    private final IntentFilter mWifiStateFilter;
+    @VisibleForTesting
+    AirplaneModeEnabler mAirplaneModeEnabler;
+
+    @VisibleForTesting
+    @Transport int mTransport;
+    private static Map<Integer, Integer> sTransportMap = new HashMap<>();
+    static {
+        sTransportMap.put(TRANSPORT_WIFI, INTERNET_WIFI);
+        sTransportMap.put(TRANSPORT_CELLULAR, INTERNET_CELLULAR);
+        sTransportMap.put(TRANSPORT_ETHERNET, INTERNET_ETHERNET);
+    }
+
+    private NetworkCallback mNetworkCallback = new NetworkCallback() {
+        @Override
+        public void onAvailable(@NonNull Network network) {
+            if (network == null) {
+                return;
+            }
+            final NetworkCapabilities networkCapabilities =
+                    mConnectivityManager.getNetworkCapabilities(network);
+            if (networkCapabilities == null) {
+                return;
+            }
+            for (@Transport int transport : networkCapabilities.getTransportTypes()) {
+                if (sTransportMap.containsKey(transport)) {
+                    mTransport = transport;
+                    break;
+                }
+            }
+            update();
+        }
+    };
+
+    private final BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            update();
+        }
+    };
+
+    public InternetUpdater(Context context, Lifecycle lifecycle,
+            OnInternetTypeChangedListener listener) {
+        if (lifecycle == null) {
+            throw new IllegalArgumentException("Lifecycle must be set");
+        }
+        mContext = context;
+        mAirplaneModeEnabler = new AirplaneModeEnabler(mContext, this);
+        mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
+        mWifiManager = mContext.getSystemService(WifiManager.class);
+        mWifiStateFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
+        mOnInternetTypeChangedListener = listener;
+        lifecycle.addObserver(this);
+    }
+
+    /** @OnLifecycleEvent(ON_RESUME) */
+    @OnLifecycleEvent(ON_RESUME)
+    public void onResume() {
+        mAirplaneModeEnabler.start();
+        mConnectivityManager.registerDefaultNetworkCallback(mNetworkCallback);
+        mContext.registerReceiver(mWifiStateReceiver, mWifiStateFilter);
+    }
+
+    /** @OnLifecycleEvent(ON_PAUSE) */
+    @OnLifecycleEvent(ON_PAUSE)
+    public void onPause() {
+        mAirplaneModeEnabler.stop();
+        mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
+        mContext.unregisterReceiver(mWifiStateReceiver);
+    }
+
+    @Override
+    public void onAirplaneModeChanged(boolean isAirplaneModeOn) {
+        update();
+    }
+
+    @VisibleForTesting
+    void update() {
+        if (mAirplaneModeEnabler.isAirplaneModeOn()) {
+            mInternetType = mWifiManager.isWifiEnabled() ? INTERNET_APM_NETWORKS : INTERNET_APM;
+        } else {
+            mInternetType = sTransportMap.get(mTransport);
+        }
+        if (mOnInternetTypeChangedListener != null) {
+            mOnInternetTypeChangedListener.onInternetTypeChanged(mInternetType);
+        }
+    }
+
+    /**
+     * Get the internet type.
+     */
+    public @InternetType int getInternetType() {
+        return mInternetType;
+    }
+}
diff --git a/src/com/android/settings/network/NetworkDashboardFragment.java b/src/com/android/settings/network/NetworkDashboardFragment.java
index 7ce98e8..14d85e9 100644
--- a/src/com/android/settings/network/NetworkDashboardFragment.java
+++ b/src/com/android/settings/network/NetworkDashboardFragment.java
@@ -113,7 +113,7 @@
                                 metricsFeatureProvider);
         final InternetPreferenceController internetPreferenceController =
                 Utils.isProviderModelEnabled(context)
-                        ? new InternetPreferenceController(context)
+                        ? new InternetPreferenceController(context, lifecycle)
                         : null;
 
         final VpnPreferenceController vpnPreferenceController =
@@ -126,9 +126,6 @@
             if (wifiPreferenceController != null) {
                 lifecycle.addObserver(wifiPreferenceController);
             }
-            if (internetPreferenceController != null) {
-                lifecycle.addObserver(internetPreferenceController);
-            }
             lifecycle.addObserver(vpnPreferenceController);
             lifecycle.addObserver(privateDnsPreferenceController);
         }
diff --git a/tests/unit/src/com/android/settings/network/InternetPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/InternetPreferenceControllerTest.java
index 02e7de3..a612177 100644
--- a/tests/unit/src/com/android/settings/network/InternetPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/InternetPreferenceControllerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.network;
 
+import static com.android.settings.network.InternetUpdater.INTERNET_WIFI;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -35,53 +37,54 @@
 import android.os.Handler;
 import android.os.Looper;
 
+import androidx.lifecycle.Lifecycle;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceManager;
 import androidx.preference.PreferenceScreen;
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
-import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
-
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 @RunWith(AndroidJUnit4.class)
 public class InternetPreferenceControllerTest {
 
     private static final String TEST_SUMMARY = "test summary";
 
+    @Rule
+    public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Mock
+    private ConnectivityManager mConnectivityManager;
+
     private Context mContext;
     private InternetPreferenceController mController;
     private PreferenceScreen mScreen;
     private Preference mPreference;
 
-    @Mock
-    private ConnectivityManager mConnectivityManager;
-
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mContext = spy(ApplicationProvider.getApplicationContext());
         when(mContext.getSystemService(ConnectivityManager.class)).thenReturn(mConnectivityManager);
         when(mContext.getSystemService(NetworkScoreManager.class))
-            .thenReturn(mock(NetworkScoreManager.class));
+                .thenReturn(mock(NetworkScoreManager.class));
         final WifiManager wifiManager = mock(WifiManager.class);
         when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
         when(wifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_DISABLED);
 
-        mController = new InternetPreferenceController(mContext);
+        mController = new InternetPreferenceController(mContext, mock(Lifecycle.class));
         if (Looper.myLooper() == null) {
             Looper.prepare();
         }
         final PreferenceManager preferenceManager = new PreferenceManager(mContext);
         mScreen = preferenceManager.createPreferenceScreen(mContext);
         mPreference = new Preference(mContext);
-        mPreference.setKey(InternetPreferenceController.KEY_INTERNET_SETTINGS);
+        mPreference.setKey(InternetPreferenceController.KEY);
         mScreen.addPreference(mPreference);
     }
 
@@ -113,6 +116,7 @@
 
     @Test
     public void onSummaryChanged_shouldUpdatePreferenceSummary() {
+        mController.onInternetTypeChanged(INTERNET_WIFI);
         mController.displayPreference(mScreen);
 
         mController.onSummaryChanged(TEST_SUMMARY);
diff --git a/tests/unit/src/com/android/settings/network/InternetUpdaterTest.java b/tests/unit/src/com/android/settings/network/InternetUpdaterTest.java
new file mode 100644
index 0000000..18998b7
--- /dev/null
+++ b/tests/unit/src/com/android/settings/network/InternetUpdaterTest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2021 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.settings.network;
+
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+
+import static com.android.settings.network.InternetUpdater.INTERNET_APM;
+import static com.android.settings.network.InternetUpdater.INTERNET_APM_NETWORKS;
+import static com.android.settings.network.InternetUpdater.INTERNET_CELLULAR;
+import static com.android.settings.network.InternetUpdater.INTERNET_ETHERNET;
+import static com.android.settings.network.InternetUpdater.INTERNET_WIFI;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.wifi.WifiManager;
+
+import androidx.lifecycle.Lifecycle;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.settings.AirplaneModeEnabler;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+@RunWith(AndroidJUnit4.class)
+public class InternetUpdaterTest {
+
+    @Rule
+    public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Mock
+    private ConnectivityManager mConnectivityManager;
+    @Mock
+    private WifiManager mWifiManager;
+    @Mock
+    private AirplaneModeEnabler mAirplaneModeEnabler;
+
+    private Context mContext;
+    private InternetUpdater mInternetUpdater;
+
+    @Before
+    public void setUp() {
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        doReturn(mConnectivityManager).when(mContext).getSystemService(
+                Context.CONNECTIVITY_SERVICE);
+        doReturn(mWifiManager).when(mContext).getSystemService(Context.WIFI_SERVICE);
+        final Lifecycle lifecycle = mock(Lifecycle.class);
+
+        mInternetUpdater = new InternetUpdater(mContext, lifecycle, null);
+        mInternetUpdater.mAirplaneModeEnabler = mAirplaneModeEnabler;
+    }
+
+    @Test
+    public void onResume_shouldRegisterCallback() {
+        mInternetUpdater.onResume();
+
+        verify(mAirplaneModeEnabler).start();
+        verify(mContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class));
+        verify(mConnectivityManager).registerDefaultNetworkCallback(
+                any(ConnectivityManager.NetworkCallback.class));
+        // Unregister callbacks
+        mInternetUpdater.onPause();
+    }
+
+    @Test
+    public void onPause_shouldUnregisterCallback() {
+        // Register callbacks first for testing
+        mInternetUpdater.onResume();
+
+        mInternetUpdater.onPause();
+
+        verify(mAirplaneModeEnabler).stop();
+        verify(mContext).unregisterReceiver(any(BroadcastReceiver.class));
+        verify(mConnectivityManager).unregisterNetworkCallback(
+                any(ConnectivityManager.NetworkCallback.class));
+    }
+
+    @Test
+    public void update_apmOnWifiOff_getInternetApm() {
+        doReturn(true).when(mAirplaneModeEnabler).isAirplaneModeOn();
+        doReturn(false).when(mWifiManager).isWifiEnabled();
+
+        mInternetUpdater.update();
+
+        assertThat(mInternetUpdater.getInternetType()).isEqualTo(INTERNET_APM);
+    }
+
+    @Test
+    public void update_apmOnWifiOn_getInternetApmNetworks() {
+        doReturn(true).when(mAirplaneModeEnabler).isAirplaneModeOn();
+        doReturn(true).when(mWifiManager).isWifiEnabled();
+
+        mInternetUpdater.update();
+
+        assertThat(mInternetUpdater.getInternetType()).isEqualTo(INTERNET_APM_NETWORKS);
+    }
+
+    @Test
+    public void update_apmOffWifiConnected_getInternetWifi() {
+        doReturn(false).when(mAirplaneModeEnabler).isAirplaneModeOn();
+        mInternetUpdater.mTransport = TRANSPORT_WIFI;
+
+        mInternetUpdater.update();
+
+        assertThat(mInternetUpdater.getInternetType()).isEqualTo(INTERNET_WIFI);
+    }
+
+    @Test
+    public void update_apmOffCellularConnected_getInternetCellular() {
+        doReturn(false).when(mAirplaneModeEnabler).isAirplaneModeOn();
+        mInternetUpdater.mTransport = TRANSPORT_CELLULAR;
+
+        mInternetUpdater.update();
+
+        assertThat(mInternetUpdater.getInternetType()).isEqualTo(INTERNET_CELLULAR);
+    }
+
+    @Test
+    public void update_apmOffEthernetConnected_getInternetEthernet() {
+        doReturn(false).when(mAirplaneModeEnabler).isAirplaneModeOn();
+        mInternetUpdater.mTransport = TRANSPORT_ETHERNET;
+
+        mInternetUpdater.update();
+
+        assertThat(mInternetUpdater.getInternetType()).isEqualTo(INTERNET_ETHERNET);
+    }
+}