Moving the error messages from slice to panel's subtitle

Bug: 180888831
Test: atest ProviderModelSliceTest
atest ProviderModelSliceHelperTest
atest NetworkProviderWorkerTest
atest InternetConnectivityPanelTest
make RunSettingsRoboTests -j

Change-Id: I4572c8ad15effab0c95feaeac6a99f5aaabf6f90
diff --git a/src/com/android/settings/network/ProviderModelSlice.java b/src/com/android/settings/network/ProviderModelSlice.java
index a1fdb1c..18765a8 100644
--- a/src/com/android/settings/network/ProviderModelSlice.java
+++ b/src/com/android/settings/network/ProviderModelSlice.java
@@ -147,31 +147,6 @@
                 listBuilder.addRow(getWifiSliceItemRow(item));
             }
         }
-
-        // Fifth section:  If device has connection problem, this row show the message for user.
-        // 1) show non_carrier_network_unavailable:
-        //    - while no wifi item
-        // 2) show all_network_unavailable:
-        //    - while no wifi item + no carrier
-        //    - while no wifi item + no data capability
-        if (worker == null || wifiList == null || wifiList.size() == 0) {
-            log("no wifi item");
-            int resId = R.string.non_carrier_network_unavailable;
-            if (!hasCarrier || !mHelper.isDataSimActive()) {
-                log("No carrier item or no carrier data.");
-                resId = R.string.all_network_unavailable;
-            }
-
-            if (!hasCarrier && !hasEthernet) {
-                // If there is no item in ProviderModelItem, slice needs a header.
-                listBuilder.setHeader(mHelper.createHeader(
-                        NetworkProviderSettings.ACTION_NETWORK_PROVIDER_SETTINGS));
-            }
-            listBuilder.addGridRow(
-                    mHelper.createMessageGridRow(resId,
-                            NetworkProviderSettings.ACTION_NETWORK_PROVIDER_SETTINGS));
-        }
-
         return listBuilder.build();
     }
 
diff --git a/src/com/android/settings/network/ProviderModelSliceHelper.java b/src/com/android/settings/network/ProviderModelSliceHelper.java
index 8ae4197..440d425 100644
--- a/src/com/android/settings/network/ProviderModelSliceHelper.java
+++ b/src/com/android/settings/network/ProviderModelSliceHelper.java
@@ -36,7 +36,6 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.core.graphics.drawable.IconCompat;
-import androidx.slice.builders.GridRowBuilder;
 import androidx.slice.builders.ListBuilder;
 import androidx.slice.builders.SliceAction;
 
@@ -79,12 +78,6 @@
         Log.d(TAG, s);
     }
 
-    protected ListBuilder.HeaderBuilder createHeader(String intentAction) {
-        return new ListBuilder.HeaderBuilder()
-                .setTitle(mContext.getText(R.string.summary_placeholder))
-                .setPrimaryAction(getPrimarySliceAction(intentAction));
-    }
-
     protected ListBuilder createListBuilder(Uri uri) {
         final ListBuilder builder = new ListBuilder(mContext, uri, ListBuilder.INFINITY)
                 .setAccentColor(-1)
@@ -92,14 +85,6 @@
         return builder;
     }
 
-    protected GridRowBuilder createMessageGridRow(int messageResId, String intentAction) {
-        final CharSequence title = mContext.getText(messageResId);
-        return new GridRowBuilder()
-                // Add cells to the grid row.
-                .addCell(new GridRowBuilder.CellBuilder().addTitleText(title))
-                .setPrimaryAction(getPrimarySliceAction(intentAction));
-    }
-
     @Nullable
     protected WifiSliceItem getConnectedWifiItem(List<WifiSliceItem> wifiList) {
         if (wifiList == null) {
@@ -111,7 +96,10 @@
         return item.isPresent() ? item.get() : null;
     }
 
-    protected boolean hasCarrier() {
+    /**
+     * @return whether there is the carrier item in the slice.
+     */
+    public boolean hasCarrier() {
         if (isAirplaneModeEnabled()
                 || mSubscriptionManager == null || mTelephonyManager == null
                 || mSubscriptionManager.getDefaultDataSubscriptionId()
@@ -175,7 +163,12 @@
         return mTelephonyManager.isDataEnabled();
     }
 
-    protected boolean isDataSimActive() {
+    /**
+     * To check the carrier data status.
+     *
+     * @return whether the carrier data is active.
+     */
+    public boolean isDataSimActive() {
         return isNoCarrierData() ? false : MobileNetworkUtils.activeNetworkIsCellular(mContext);
     }
 
@@ -193,11 +186,6 @@
         return mobileDataOnAndNoData || mobileDataOffAndOutOfService;
     }
 
-    private boolean isAirplaneSafeNetworksModeEnabled() {
-        // TODO: isAirplaneSafeNetworksModeEnabled is not READY
-        return false;
-    }
-
     @VisibleForTesting
     Drawable getMobileDrawable(Drawable drawable) throws Throwable {
         // set color and drawable
diff --git a/src/com/android/settings/panel/InternetConnectivityPanel.java b/src/com/android/settings/panel/InternetConnectivityPanel.java
index 4fda0a4..238cbb4 100644
--- a/src/com/android/settings/panel/InternetConnectivityPanel.java
+++ b/src/com/android/settings/panel/InternetConnectivityPanel.java
@@ -22,10 +22,23 @@
 import static com.android.settings.network.NetworkProviderSettings.ACTION_NETWORK_PROVIDER_SETTINGS;
 
 import android.app.settings.SettingsEnums;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.net.Uri;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.Looper;
 import android.provider.Settings;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.lifecycle.LifecycleObserver;
@@ -35,6 +48,9 @@
 import com.android.settings.Utils;
 import com.android.settings.network.AirplaneModePreferenceController;
 import com.android.settings.network.InternetUpdater;
+import com.android.settings.network.ProviderModelSliceHelper;
+import com.android.settings.network.SubscriptionsChangeListener;
+import com.android.settings.network.telephony.DataConnectivityListener;
 import com.android.settings.slices.CustomSliceRegistry;
 
 import java.util.ArrayList;
@@ -44,23 +60,69 @@
  * Represents the Internet Connectivity Panel.
  */
 public class InternetConnectivityPanel implements PanelContent, LifecycleObserver,
-        InternetUpdater.InternetChangeListener {
+        InternetUpdater.InternetChangeListener, DataConnectivityListener.Client,
+        SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
+    private static final String TAG = "InternetConnectivityPanel";
+    private static final int SUBTITLE_TEXT_NONE = -1;
+    private static final int SUBTITLE_TEXT_WIFI_IS_TURNED_ON = R.string.wifi_is_turned_on_subtitle;
+    private static final int SUBTITLE_TEXT_NON_CARRIER_NETWORK_UNAVAILABLE =
+            R.string.non_carrier_network_unavailable;
+    private static final int SUBTITLE_TEXT_ALL_CARRIER_NETWORK_UNAVAILABLE =
+            R.string.all_network_unavailable;
 
     private final Context mContext;
+    private final WifiManager mWifiManager;
+    private final IntentFilter mWifiStateFilter;
+    private final NetworkProviderTelephonyCallback mTelephonyCallback;
+    private final BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent == null) {
+                return;
+            }
+            if (TextUtils.equals(intent.getAction(), WifiManager.NETWORK_STATE_CHANGED_ACTION)
+                    || TextUtils.equals(intent.getAction(),
+                    WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
+                updatePanelTitle();
+            }
+        }
+    };
+
     @VisibleForTesting
     boolean mIsProviderModelEnabled;
-    private PanelContentCallback mCallback;
     @VisibleForTesting
     InternetUpdater mInternetUpdater;
+    @VisibleForTesting
+    ProviderModelSliceHelper mProviderModelSliceHelper;
 
-    public static InternetConnectivityPanel create(Context context) {
-        return new InternetConnectivityPanel(context);
-    }
+    private int mSubtitle = SUBTITLE_TEXT_NONE;
+    private PanelContentCallback mCallback;
+    private TelephonyManager mTelephonyManager;
+    private SubscriptionsChangeListener mSubscriptionsListener;
+    private DataConnectivityListener mConnectivityListener;
+    private int mDefaultDataSubid = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
     private InternetConnectivityPanel(Context context) {
         mContext = context.getApplicationContext();
         mIsProviderModelEnabled = Utils.isProviderModelEnabled(mContext);
         mInternetUpdater = new InternetUpdater(context, null /* Lifecycle */, this);
+
+        mSubscriptionsListener = new SubscriptionsChangeListener(context, this);
+        mConnectivityListener = new DataConnectivityListener(context, this);
+        mTelephonyCallback = new NetworkProviderTelephonyCallback();
+        mDefaultDataSubid = getDefaultDataSubscriptionId();
+        mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+
+        mWifiManager = mContext.getSystemService(WifiManager.class);
+        mWifiStateFilter = new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+        mWifiStateFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
+
+        mProviderModelSliceHelper = new ProviderModelSliceHelper(mContext, null);
+    }
+
+    /** create the panel */
+    public static InternetConnectivityPanel create(Context context) {
+        return new InternetConnectivityPanel(context);
     }
 
     /** @OnLifecycleEvent(ON_RESUME) */
@@ -70,6 +132,12 @@
             return;
         }
         mInternetUpdater.onResume();
+        mSubscriptionsListener.start();
+        mConnectivityListener.start();
+        mTelephonyManager.registerTelephonyCallback(
+                new HandlerExecutor(new Handler(Looper.getMainLooper())), mTelephonyCallback);
+        mContext.registerReceiver(mWifiStateReceiver, mWifiStateFilter);
+        updatePanelTitle();
     }
 
     /** @OnLifecycleEvent(ON_PAUSE) */
@@ -79,6 +147,10 @@
             return;
         }
         mInternetUpdater.onPause();
+        mSubscriptionsListener.stop();
+        mConnectivityListener.stop();
+        mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback);
+        mContext.unregisterReceiver(mWifiStateReceiver);
     }
 
     /**
@@ -98,9 +170,8 @@
      */
     @Override
     public CharSequence getSubTitle() {
-        if (mIsProviderModelEnabled && mInternetUpdater.isAirplaneModeOn()
-                && mInternetUpdater.isWifiEnabled()) {
-            return mContext.getText(R.string.wifi_is_turned_on_subtitle);
+        if (mIsProviderModelEnabled && mSubtitle != SUBTITLE_TEXT_NONE) {
+            return mContext.getText(mSubtitle);
         }
         return null;
     }
@@ -170,15 +241,36 @@
         updatePanelTitle();
     }
 
-    private void updatePanelTitle() {
+    @Override
+    public void onSubscriptionsChanged() {
+        final int defaultDataSubId = getDefaultDataSubscriptionId();
+        log("onSubscriptionsChanged: defaultDataSubId:" + defaultDataSubId);
+        if (mDefaultDataSubid == defaultDataSubId) {
+            return;
+        }
+        if (SubscriptionManager.isUsableSubscriptionId(defaultDataSubId)) {
+            mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback);
+            mTelephonyManager.registerTelephonyCallback(
+                    new HandlerExecutor(new Handler(Looper.getMainLooper())), mTelephonyCallback);
+        }
+        updatePanelTitle();
+    }
+
+    @Override
+    public void onDataConnectivityChange() {
+        log("onDataConnectivityChange");
+        updatePanelTitle();
+    }
+
+    @VisibleForTesting
+    void updatePanelTitle() {
         if (mCallback == null) {
             return;
         }
+        updateSubtitleText();
 
-        if (mInternetUpdater.isAirplaneModeOn() && mInternetUpdater.isWifiEnabled()) {
-            // When the airplane mode is on and Wi-Fi is enabled.
-            //   Title: Airplane mode
-            //   Sub-Title: Wi-Fi is turned on
+        log("Subtitle:" + mSubtitle);
+        if (mSubtitle != SUBTITLE_TEXT_NONE) {
             mCallback.onHeaderChanged();
         } else {
             // Other situations.
@@ -187,4 +279,63 @@
         }
         mCallback.onCustomizedButtonStateChanged();
     }
+
+    @VisibleForTesting
+    int getDefaultDataSubscriptionId() {
+        return SubscriptionManager.getDefaultDataSubscriptionId();
+    }
+
+    private void updateSubtitleText() {
+        mSubtitle = SUBTITLE_TEXT_NONE;
+        if (!mInternetUpdater.isWifiEnabled()) {
+            return;
+        }
+
+        if (mInternetUpdater.isAirplaneModeOn()) {
+            // When the airplane mode is on and Wi-Fi is enabled.
+            //   Title: Airplane mode
+            //   Sub-Title: Wi-Fi is turned on
+            log("Airplane mode is on + Wi-Fi on.");
+            mSubtitle = SUBTITLE_TEXT_WIFI_IS_TURNED_ON;
+            return;
+        }
+
+        final List<ScanResult> wifiList = mWifiManager.getScanResults();
+        if (wifiList != null && wifiList.size() == 0) {
+            // Sub-Title:
+            // show non_carrier_network_unavailable
+            //   - while Wi-Fi on + no Wi-Fi item
+            // show all_network_unavailable:
+            //   - while Wi-Fi on + no Wi-Fi item + no carrier
+            //   - while Wi-Fi on + no Wi-Fi item + no data capability
+            log("No Wi-Fi item.");
+            mSubtitle = SUBTITLE_TEXT_NON_CARRIER_NETWORK_UNAVAILABLE;
+            if (!mProviderModelSliceHelper.hasCarrier()
+                    || !mProviderModelSliceHelper.isDataSimActive()) {
+                log("No carrier item or no carrier data.");
+                mSubtitle = SUBTITLE_TEXT_ALL_CARRIER_NETWORK_UNAVAILABLE;
+            }
+        }
+    }
+
+    private class NetworkProviderTelephonyCallback extends TelephonyCallback implements
+            TelephonyCallback.DataConnectionStateListener,
+            TelephonyCallback.ServiceStateListener {
+        @Override
+        public void onServiceStateChanged(ServiceState state) {
+            log("onServiceStateChanged voiceState=" + state.getState()
+                    + " dataState=" + state.getDataRegistrationState());
+            updatePanelTitle();
+        }
+
+        @Override
+        public void onDataConnectionStateChanged(int state, int networkType) {
+            log("onDataConnectionStateChanged: networkType=" + networkType + " state=" + state);
+            updatePanelTitle();
+        }
+    }
+
+    private static void log(String s) {
+        Log.d(TAG, s);
+    }
 }
diff --git a/tests/unit/src/com/android/settings/network/ProviderModelSliceHelperTest.java b/tests/unit/src/com/android/settings/network/ProviderModelSliceHelperTest.java
index d205607..ac2e24d 100644
--- a/tests/unit/src/com/android/settings/network/ProviderModelSliceHelperTest.java
+++ b/tests/unit/src/com/android/settings/network/ProviderModelSliceHelperTest.java
@@ -34,7 +34,6 @@
 import android.net.NetworkCapabilities;
 import android.net.Uri;
 import android.os.PersistableBundle;
-import android.provider.Settings;
 import android.telephony.CarrierConfigManager;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
@@ -43,8 +42,6 @@
 import android.text.Html;
 
 import androidx.slice.Slice;
-import androidx.slice.builders.GridRowBuilder;
-import androidx.slice.builders.GridRowBuilder.CellBuilder;
 import androidx.slice.builders.ListBuilder;
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -115,20 +112,6 @@
     }
 
     @Test
-    public void createMessageGridRow_inputTheResourceId_verifyTitle() {
-        int messageResId = ResourcesUtils.getResourcesId(mContext, "string",
-                "non_carrier_network_unavailable");
-        CharSequence title = ResourcesUtils.getResourcesString(mContext,
-                "non_carrier_network_unavailable");
-
-        GridRowBuilder testGridRow = mProviderModelSliceHelper.createMessageGridRow(messageResId,
-                Settings.ACTION_AIRPLANE_MODE_SETTINGS);
-        List<CellBuilder> cellItem = testGridRow.getCells();
-
-        assertThat(cellItem.get(0).getTitle()).isEqualTo(title);
-    }
-
-    @Test
     public void getConnectedWifiItem_inputListInvolveOneConnectedWifiItem_verifyReturnItem() {
         when(mWifiSliceItem1.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED);
         when(mWifiSliceItem2.getConnectedState()).thenReturn(
diff --git a/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java b/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java
index 705f60e..4760daa 100644
--- a/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java
+++ b/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java
@@ -22,7 +22,6 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
@@ -42,7 +41,6 @@
 
 import androidx.slice.Slice;
 import androidx.slice.SliceProvider;
-import androidx.slice.builders.GridRowBuilder;
 import androidx.slice.builders.ListBuilder;
 import androidx.slice.builders.SliceAction;
 import androidx.slice.widget.SliceLiveData;
@@ -97,12 +95,6 @@
     private WifiSliceItem mMockWifiSliceItem3;
     @Mock
     ListBuilder.RowBuilder mMockCarrierRowBuild;
-    @Mock
-    ListBuilder.HeaderBuilder mMockHeader;
-    @Mock
-    GridRowBuilder mMockGridRowBuilderNonCarrierNetworkUnavailable;
-    @Mock
-    GridRowBuilder mMockGridRowBuilderAllNetworkUnavailable;
 
     private FakeFeatureFactory mFeatureFactory;
     @Mock
@@ -147,35 +139,7 @@
 
     @Test
     @UiThreadTest
-    public void getSlice_noWorkerAndNoCarrier_getOneHeaderOneGridRowWithAllNetworkUnavailable() {
-        mWifiList.clear();
-        mMockProviderModelSlice = new MockProviderModelSlice(mContext, null);
-        mockHelperCondition(false, false, false, null);
-
-        final Slice slice = mMockProviderModelSlice.getSlice();
-
-        assertThat(slice).isNotNull();
-        verify(mListBuilder, times(1)).setHeader(mMockHeader);
-        verify(mListBuilder, times(1)).addGridRow(mMockGridRowBuilderAllNetworkUnavailable);
-    }
-
-    @Test
-    @UiThreadTest
-    public void getSlice_noWifiAndNoCarrier_getOneHeaderOneGridRowWithAllNetworkUnavailable() {
-        mWifiList.clear();
-        mMockNetworkProviderWorker.updateSelfResults(null);
-        mockHelperCondition(false, false, false, null);
-
-        final Slice slice = mMockProviderModelSlice.getSlice();
-
-        assertThat(slice).isNotNull();
-        verify(mListBuilder, times(1)).setHeader(mMockHeader);
-        verify(mListBuilder, times(1)).addGridRow(mMockGridRowBuilderAllNetworkUnavailable);
-    }
-
-    @Test
-    @UiThreadTest
-    public void getSlice_noWifiAndHasCarrierNoData_oneCarrierOneGridRowWithAllNetworkUnavailable() {
+    public void getSlice_noWifiAndHasCarrierNoData_oneCarrier() {
         mWifiList.clear();
         mMockNetworkProviderWorker.updateSelfResults(null);
         mockHelperCondition(false, true, false, null);
@@ -184,12 +148,11 @@
 
         assertThat(slice).isNotNull();
         verify(mListBuilder, times(1)).addRow(mMockCarrierRowBuild);
-        verify(mListBuilder, times(1)).addGridRow(mMockGridRowBuilderAllNetworkUnavailable);
     }
 
     @Test
     @UiThreadTest
-    public void getSlice_noWifiAndNoCarrier_oneCarrierOneGridRowWithNonCarrierNetworkUnavailable() {
+    public void getSlice_noWifiAndNoCarrier_oneCarrier() {
         mWifiList.clear();
         mMockProviderModelSlice = new MockProviderModelSlice(mContext, null);
         mockHelperCondition(false, true, true, null);
@@ -198,7 +161,6 @@
 
         assertThat(slice).isNotNull();
         verify(mListBuilder, times(1)).addRow(mMockCarrierRowBuild);
-        verify(mListBuilder, times(1)).addGridRow(mMockGridRowBuilderNonCarrierNetworkUnavailable);
     }
 
     @Test
@@ -331,19 +293,6 @@
 
     private void mockBuilder() {
         SliceAction mockSliceAction = getPrimarySliceAction();
-        when(mMockHeader.getTitle()).thenReturn("mockHeader");
-        when(mMockHeader.getPrimaryAction()).thenReturn(mockSliceAction);
-        when(mProviderModelSliceHelper.createHeader(anyString())).thenReturn(mMockHeader);
-
-        int resId = ResourcesUtils.getResourcesId(mContext, "string",
-                "non_carrier_network_unavailable");
-        when(mProviderModelSliceHelper.createMessageGridRow(eq(resId), anyString())).thenReturn(
-                mMockGridRowBuilderNonCarrierNetworkUnavailable);
-        resId = ResourcesUtils.getResourcesId(mContext, "string",
-                "all_network_unavailable");
-        when(mProviderModelSliceHelper.createMessageGridRow(eq(resId), anyString())).thenReturn(
-                mMockGridRowBuilderAllNetworkUnavailable);
-
         when(mMockCarrierRowBuild.getTitle()).thenReturn("mockRow");
         when(mMockCarrierRowBuild.getPrimaryAction()).thenReturn(mockSliceAction);
         when(mProviderModelSliceHelper.createCarrierRow(anyString())).thenReturn(
diff --git a/tests/unit/src/com/android/settings/panel/InternetConnectivityPanelTest.java b/tests/unit/src/com/android/settings/panel/InternetConnectivityPanelTest.java
index ba5ee8e..8f0cfb3 100644
--- a/tests/unit/src/com/android/settings/panel/InternetConnectivityPanelTest.java
+++ b/tests/unit/src/com/android/settings/panel/InternetConnectivityPanelTest.java
@@ -22,15 +22,19 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.net.Uri;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiManager;
 
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
 import com.android.settings.network.AirplaneModePreferenceController;
 import com.android.settings.network.InternetUpdater;
+import com.android.settings.network.ProviderModelSliceHelper;
 import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settings.testutils.ResourcesUtils;
 
@@ -42,6 +46,7 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
+import java.util.ArrayList;
 import java.util.List;
 
 @RunWith(AndroidJUnit4.class)
@@ -55,6 +60,12 @@
             ApplicationProvider.getApplicationContext(), "wifi_is_turned_on_subtitle");
     public static final String BUTTON_SETTINGS = ResourcesUtils.getResourcesString(
             ApplicationProvider.getApplicationContext(), "settings_button");
+    public static final String SUBTITLE_NON_CARRIER_NETWORK_UNAVAILABLE =
+            ResourcesUtils.getResourcesString(ApplicationProvider.getApplicationContext(),
+                    "non_carrier_network_unavailable");
+    public static final String SUBTITLE_ALL_NETWORK_UNAVAILABLE =
+            ResourcesUtils.getResourcesString(ApplicationProvider.getApplicationContext(),
+                    "all_network_unavailable");
 
     @Rule
     public final MockitoRule mMocks = MockitoJUnit.rule();
@@ -62,6 +73,10 @@
     PanelContentCallback mPanelContentCallback;
     @Mock
     InternetUpdater mInternetUpdater;
+    @Mock
+    private WifiManager mWifiManager;
+    @Mock
+    private ProviderModelSliceHelper mProviderModelSliceHelper;
 
     private Context mContext;
     private InternetConnectivityPanel mPanel;
@@ -69,11 +84,14 @@
     @Before
     public void setUp() {
         mContext = spy(ApplicationProvider.getApplicationContext());
+        when(mContext.getApplicationContext()).thenReturn(mContext);
+        when(mContext.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
 
         mPanel = InternetConnectivityPanel.create(mContext);
         mPanel.registerCallback(mPanelContentCallback);
         mPanel.mIsProviderModelEnabled = true;
         mPanel.mInternetUpdater = mInternetUpdater;
+        mPanel.mProviderModelSliceHelper = mProviderModelSliceHelper;
     }
 
     @Test
@@ -91,13 +109,6 @@
     }
 
     @Test
-    public void getSubTitle_apmOff_shouldBeNull() {
-        doReturn(false).when(mInternetUpdater).isAirplaneModeOn();
-
-        assertThat(mPanel.getSubTitle()).isNull();
-    }
-
-    @Test
     public void getSubTitle_apmOnWifiOff_shouldBeNull() {
         doReturn(true).when(mInternetUpdater).isAirplaneModeOn();
         doReturn(false).when(mInternetUpdater).isWifiEnabled();
@@ -110,10 +121,44 @@
         doReturn(true).when(mInternetUpdater).isAirplaneModeOn();
         doReturn(true).when(mInternetUpdater).isWifiEnabled();
 
+        mPanel.updatePanelTitle();
+
         assertThat(mPanel.getSubTitle()).isEqualTo(SUBTITLE_WIFI_IS_TURNED_ON);
     }
 
     @Test
+    public void getSubTitle_apmOffWifiOnNoWifiListHasCarrierData_NonCarrierNetworkUnavailable() {
+        List wifiList = new ArrayList<ScanResult>();
+        mockCondition(false, true, true, true, wifiList);
+
+        mPanel.updatePanelTitle();
+
+        assertThat(mPanel.getSubTitle()).isEqualTo(SUBTITLE_NON_CARRIER_NETWORK_UNAVAILABLE);
+    }
+
+    @Test
+    public void getSubTitle_apmOffWifiOnNoWifiListNoCarrierData_AllNetworkUnavailable() {
+        List wifiList = new ArrayList<ScanResult>();
+        mockCondition(false, true, false, true, wifiList);
+
+        mPanel.updatePanelTitle();
+
+        assertThat(mPanel.getSubTitle()).isEqualTo(SUBTITLE_ALL_NETWORK_UNAVAILABLE);
+    }
+
+    @Test
+    public void getSubTitle_apmOffWifiOnTwoWifiItemsNoCarrierData_shouldBeNull() {
+        List wifiList = new ArrayList<ScanResult>();
+        wifiList.add(new ScanResult());
+        wifiList.add(new ScanResult());
+        mockCondition(false, true, false, true, wifiList);
+
+        mPanel.updatePanelTitle();
+
+        assertThat(mPanel.getSubTitle()).isNull();
+    }
+
+    @Test
     public void getCustomizedButtonTitle_apmOff_shouldBeSettings() {
         doReturn(false).when(mInternetUpdater).isAirplaneModeOn();
 
@@ -244,4 +289,13 @@
 
         verify(mPanelContentCallback).onCustomizedButtonStateChanged();
     }
+
+    private void mockCondition(boolean airplaneMode, boolean hasCarrier,
+            boolean isDataSimActive, boolean isWifiEnabled, List<ScanResult> wifiItems) {
+        doReturn(airplaneMode).when(mInternetUpdater).isAirplaneModeOn();
+        when(mProviderModelSliceHelper.hasCarrier()).thenReturn(hasCarrier);
+        when(mProviderModelSliceHelper.isDataSimActive()).thenReturn(isDataSimActive);
+        doReturn(isWifiEnabled).when(mInternetUpdater).isWifiEnabled();
+        doReturn(wifiItems).when(mWifiManager).getScanResults();
+    }
 }