[Provider Model] Add Wi-Fi toggle in internet panel

- Add a new slice row for Wi-Fi toggle in the network lists

- Increase the maximum number of network lists to 6

Bug: 189912933
Test: manual test
atest -c ProviderModelSliceTest

Change-Id: Ie25e108573f264ab3a94fc6804b9d46d855eeea1
diff --git a/src/com/android/settings/network/ProviderModelSlice.java b/src/com/android/settings/network/ProviderModelSlice.java
index aafe715..df705cd 100644
--- a/src/com/android/settings/network/ProviderModelSlice.java
+++ b/src/com/android/settings/network/ProviderModelSlice.java
@@ -16,10 +16,10 @@
 
 package com.android.settings.network;
 
-
 import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
 
 import static com.android.settings.slices.CustomSliceRegistry.PROVIDER_MODEL_SLICE_URI;
+import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI;
 
 import android.annotation.ColorInt;
 import android.app.AlertDialog;
@@ -96,78 +96,77 @@
     @Override
     public Slice getSlice() {
         // The provider model slice step:
-        // First section:  Add a Wi-Fi item which state is connected.
-        // Second section:  Add a carrier item.
-        // Third section:  Add the Wi-Fi items which are not connected.
-        // Fourth section:  If device has connection problem, this row show the message for user.
-        @InternetUpdater.InternetType int internetType = getInternetType();
+        //  First section: Add the Ethernet item.
+        // Second section: Add the carrier item.
+        //  Third section: Add the Wi-Fi toggle item.
+        // Fourth section: Add the connected Wi-Fi item.
+        //  Fifth section: Add the Wi-Fi items which are not connected.
+        //  Sixth section: Add the See All item.
         final ListBuilder listBuilder = mHelper.createListBuilder(getUri());
-        if (mHelper.isAirplaneModeEnabled() && !mWifiManager.isWifiEnabled()
-                && internetType != InternetUpdater.INTERNET_ETHERNET) {
-            log("Airplane mode is enabled.");
-            return listBuilder.build();
-        }
-
         int maxListSize = 0;
-        List<WifiSliceItem> wifiList = null;
         final NetworkProviderWorker worker = getWorker();
         if (worker != null) {
-            // get Wi-Fi list.
-            wifiList = worker.getResults();
             maxListSize = worker.getApRowCount();
         } else {
             log("network provider worker is null.");
         }
 
-        final boolean hasCarrier = mHelper.hasCarrier();
-        log("hasCarrier: " + hasCarrier);
-
-        // First section:  Add a Ethernet or Wi-Fi item which state is connected.
-        boolean isConnectedWifiAddedTop = false;
-        final WifiSliceItem connectedWifiItem = mHelper.getConnectedWifiItem(wifiList);
-        if (internetType == InternetUpdater.INTERNET_ETHERNET) {
+        // First section: Add the Ethernet item.
+        if (getInternetType() == InternetUpdater.INTERNET_ETHERNET) {
             log("get Ethernet item which is connected");
             listBuilder.addRow(createEthernetRow());
             maxListSize--;
-        } else {
-            if (connectedWifiItem != null && internetType == InternetUpdater.INTERNET_WIFI) {
-                log("get Wi-Fi item which is connected to internet");
-                listBuilder.addRow(getWifiSliceItemRow(connectedWifiItem));
-                isConnectedWifiAddedTop = true;
+        }
+
+        // Second section: Add the carrier item.
+        if (!mHelper.isAirplaneModeEnabled()) {
+            final boolean hasCarrier = mHelper.hasCarrier();
+            log("hasCarrier: " + hasCarrier);
+            if (hasCarrier) {
+                mHelper.updateTelephony();
+                listBuilder.addRow(
+                        mHelper.createCarrierRow(
+                                worker != null ? worker.getNetworkTypeDescription() : ""));
                 maxListSize--;
             }
         }
 
-        // Second section:  Add a carrier item.
-        if (hasCarrier) {
-            mHelper.updateTelephony();
-            listBuilder.addRow(
-                    mHelper.createCarrierRow(
-                            worker != null ? worker.getNetworkTypeDescription() : ""));
-            maxListSize--;
+        // Third section: Add the Wi-Fi toggle item.
+        final boolean isWifiEnabled = mWifiManager.isWifiEnabled();
+        listBuilder.addRow(createWifiToggleRow(mContext, isWifiEnabled));
+        maxListSize--;
+        if (!isWifiEnabled) {
+            log("Wi-Fi is disabled");
+            return listBuilder.build();
+        }
+        List<WifiSliceItem> wifiList = (worker != null) ? worker.getResults() : null;
+        if (wifiList == null || wifiList.size() <= 0) {
+            log("Wi-Fi list is empty");
+            return listBuilder.build();
         }
 
-        // Third section:  Add the connected Wi-Fi item to Wi-Fi list if the Ethernet is connected.
-        if (connectedWifiItem != null && !isConnectedWifiAddedTop) {
+        // Fourth section: Add the connected Wi-Fi item.
+        final WifiSliceItem connectedWifiItem = mHelper.getConnectedWifiItem(wifiList);
+        if (connectedWifiItem != null) {
             log("get Wi-Fi item which is connected");
             listBuilder.addRow(getWifiSliceItemRow(connectedWifiItem));
             maxListSize--;
         }
 
-        // Fourth section:  Add the Wi-Fi items which are not connected.
-        if (wifiList != null && wifiList.size() > 0) {
-            log("get Wi-Fi items which are not connected. Wi-Fi items : " + wifiList.size());
-
-            final List<WifiSliceItem> disconnectedWifiList = wifiList.stream()
-                    .filter(wifiSliceItem -> wifiSliceItem.getConnectedState()
-                            != WifiEntry.CONNECTED_STATE_CONNECTED)
-                    .limit(maxListSize - 1)
-                    .collect(Collectors.toList());
-            for (WifiSliceItem item : disconnectedWifiList) {
-                listBuilder.addRow(getWifiSliceItemRow(item));
-            }
-            listBuilder.addRow(getSeeAllRow());
+        // Fifth section: Add the Wi-Fi items which are not connected.
+        log("get Wi-Fi items which are not connected. Wi-Fi items : " + wifiList.size());
+        final List<WifiSliceItem> disconnectedWifiList = wifiList.stream()
+                .filter(item -> item.getConnectedState() != WifiEntry.CONNECTED_STATE_CONNECTED)
+                .limit(maxListSize - 1)
+                .collect(Collectors.toList());
+        for (WifiSliceItem item : disconnectedWifiList) {
+            listBuilder.addRow(getWifiSliceItemRow(item));
         }
+
+        // Sixth section: Add the See All item.
+        log("add See-All");
+        listBuilder.addRow(getSeeAllRow());
+
         return listBuilder.build();
     }
 
@@ -324,6 +323,26 @@
                 .setSubtitle(mContext.getText(R.string.to_switch_networks_disconnect_ethernet));
     }
 
+    /**
+     * @return a {@link ListBuilder.RowBuilder} of the Wi-Fi toggle.
+     */
+    protected ListBuilder.RowBuilder createWifiToggleRow(Context context, boolean isWifiEnabled) {
+        final Intent intent = new Intent(WIFI_SLICE_URI.toString())
+                .setData(WIFI_SLICE_URI)
+                .setClass(context, SliceBroadcastReceiver.class)
+                .putExtra(EXTRA_TOGGLE_STATE, !isWifiEnabled)
+                // The FLAG_RECEIVER_FOREGROUND flag is necessary to avoid the intent delay of
+                // the first sending after the device restarts
+                .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+        final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent,
+                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
+        final SliceAction toggleSliceAction = SliceAction.createToggle(pendingIntent,
+                null /* actionTitle */, isWifiEnabled);
+        return new ListBuilder.RowBuilder()
+                .setTitle(context.getString(R.string.wifi_settings))
+                .setPrimaryAction(toggleSliceAction);
+    }
+
     protected ListBuilder.RowBuilder getSeeAllRow() {
         final CharSequence title = mContext.getText(R.string.previous_connected_see_all);
         final IconCompat icon = getSeeAllIcon();
diff --git a/src/com/android/settings/network/telephony/NetworkProviderWorker.java b/src/com/android/settings/network/telephony/NetworkProviderWorker.java
index 675d60f..a6b438a 100644
--- a/src/com/android/settings/network/telephony/NetworkProviderWorker.java
+++ b/src/com/android/settings/network/telephony/NetworkProviderWorker.java
@@ -54,7 +54,7 @@
         DataConnectivityListener.Client, InternetUpdater.InternetChangeListener,
         SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
     private static final String TAG = "NetworkProviderWorker";
-    private static final int PROVIDER_MODEL_DEFAULT_EXPANDED_ROW_COUNT = 5;
+    private static final int PROVIDER_MODEL_DEFAULT_EXPANDED_ROW_COUNT = 6;
     private DataContentObserver mMobileDataObserver;
     private SignalStrengthListener mSignalStrengthListener;
     private SubscriptionsChangeListener mSubscriptionsListener;
diff --git a/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java b/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java
index 722e305..66247d3 100644
--- a/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java
+++ b/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java
@@ -46,6 +46,8 @@
 import android.telephony.TelephonyManager;
 
 import androidx.slice.Slice;
+import androidx.slice.SliceItem;
+import androidx.slice.SliceMetadata;
 import androidx.slice.SliceProvider;
 import androidx.slice.builders.ListBuilder;
 import androidx.slice.builders.SliceAction;
@@ -104,8 +106,6 @@
     ListBuilder.RowBuilder mMockCarrierRowBuild;
     @Mock
     WifiPickerTracker mWifiPickerTracker;
-    @Mock
-    WifiSliceItem mWifiSliceItem;
     AlertDialog mMockAlertDialog;
 
     private FakeFeatureFactory mFeatureFactory;
@@ -127,7 +127,7 @@
         when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
         when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
         when(mContext.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
-
+        when(mWifiManager.isWifiEnabled()).thenReturn(true);
 
         // Set-up specs for SliceMetadata.
         SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
@@ -192,7 +192,24 @@
 
     @Test
     @UiThreadTest
-    public void getSlice_haveTwoWifiAndOneCarrier_getCarrierAndTwoWiFiAndSeeAll() {
+    public void getSlice_airplaneModeIsOn_oneWifiToggle() {
+        mWifiList.clear();
+        mMockNetworkProviderWorker.updateSelfResults(null);
+        mockHelperCondition(true, false, false, null);
+
+        final Slice slice = mMockProviderModelSlice.getSlice();
+
+        assertThat(slice).isNotNull();
+        verify(mListBuilder, times(1)).addRow(any(ListBuilder.RowBuilder.class));
+        final SliceItem sliceTitle =
+                SliceMetadata.from(mContext, slice).getListContent().getHeader().getTitleItem();
+        assertThat(sliceTitle.getText()).isEqualTo(
+                ResourcesUtils.getResourcesString(mContext, "wifi_settings"));
+    }
+
+    @Test
+    @UiThreadTest
+    public void getSlice_haveTwoWifiAndOneCarrier_getFiveRow() {
         mWifiList.clear();
         mockWifiItemCondition(mMockWifiSliceItem1, "wifi1", "wifi1",
                 WifiEntry.CONNECTED_STATE_CONNECTED, "wifi1_key", true);
@@ -207,13 +224,13 @@
 
         assertThat(slice).isNotNull();
         verify(mListBuilder, times(1)).addRow(mMockCarrierRowBuild);
-        verify(mListBuilder, times(4)).addRow(any(ListBuilder.RowBuilder.class));
+        verify(mListBuilder, times(5)).addRow(any(ListBuilder.RowBuilder.class));
         assertThat(mMockProviderModelSlice.hasSeeAllRow()).isTrue();
     }
 
     @Test
     @UiThreadTest
-    public void getSlice_haveOneConnectedWifiAndTwoDisconnectedWifiAndNoCarrier_getFourRow() {
+    public void getSlice_haveOneConnectedWifiAndTwoDisconnectedWifiAndNoCarrier_getFiveRow() {
         mWifiList.clear();
         mockWifiItemCondition(mMockWifiSliceItem1, "wifi1", "wifi1",
                 WifiEntry.CONNECTED_STATE_CONNECTED, "wifi1_key", true);
@@ -230,13 +247,13 @@
         final Slice slice = mMockProviderModelSlice.getSlice();
 
         assertThat(slice).isNotNull();
-        verify(mListBuilder, times(4)).addRow(any(ListBuilder.RowBuilder.class));
+        verify(mListBuilder, times(5)).addRow(any(ListBuilder.RowBuilder.class));
         assertThat(mMockProviderModelSlice.hasSeeAllRow()).isTrue();
     }
 
     @Test
     @UiThreadTest
-    public void getSlice_haveTwoDisconnectedWifiAndNoCarrier_getThreeRow() {
+    public void getSlice_haveTwoDisconnectedWifiAndNoCarrier_getFourRow() {
         mWifiList.clear();
         mockWifiItemCondition(mMockWifiSliceItem1, "wifi1", "wifi1",
                 WifiEntry.CONNECTED_STATE_DISCONNECTED, "wifi1_key", true);
@@ -250,13 +267,13 @@
         final Slice slice = mMockProviderModelSlice.getSlice();
 
         assertThat(slice).isNotNull();
-        verify(mListBuilder, times(3)).addRow(any(ListBuilder.RowBuilder.class));
+        verify(mListBuilder, times(4)).addRow(any(ListBuilder.RowBuilder.class));
         assertThat(mMockProviderModelSlice.hasSeeAllRow()).isTrue();
     }
 
     @Test
     @UiThreadTest
-    public void getSlice_haveEthernetAndCarrierAndTwoDisconnectedWifi_getFiveRow() {
+    public void getSlice_haveEthernetAndCarrierAndTwoDisconnectedWifi_getSixRow() {
         mWifiList.clear();
         mockWifiItemCondition(mMockWifiSliceItem1, "wifi1", "wifi1",
                 WifiEntry.CONNECTED_STATE_DISCONNECTED, "wifi1_key", true);
@@ -274,13 +291,13 @@
         assertThat(slice).isNotNull();
         assertThat(mMockProviderModelSlice.hasCreateEthernetRow()).isTrue();
         verify(mListBuilder, times(1)).addRow(mMockCarrierRowBuild);
-        verify(mListBuilder, times(5)).addRow(any(ListBuilder.RowBuilder.class));
+        verify(mListBuilder, times(6)).addRow(any(ListBuilder.RowBuilder.class));
         assertThat(mMockProviderModelSlice.hasSeeAllRow()).isTrue();
     }
 
     @Test
     @UiThreadTest
-    public void getSlice_haveEthernetAndCarrierAndConnectedWifiAndDisconnectedWifi_getFiveRow() {
+    public void getSlice_haveEthernetAndCarrierAndConnectedWifiAndDisconnectedWifi_getSixRow() {
         mWifiList.clear();
         mockWifiItemCondition(mMockWifiSliceItem1, "wifi1", "wifi1",
                 WifiEntry.CONNECTED_STATE_CONNECTED, "wifi1_key", true);
@@ -298,7 +315,7 @@
         assertThat(slice).isNotNull();
         assertThat(mMockProviderModelSlice.hasCreateEthernetRow()).isTrue();
         verify(mListBuilder, times(1)).addRow(mMockCarrierRowBuild);
-        verify(mListBuilder, times(5)).addRow(any(ListBuilder.RowBuilder.class));
+        verify(mListBuilder, times(6)).addRow(any(ListBuilder.RowBuilder.class));
         assertThat(mMockProviderModelSlice.hasSeeAllRow()).isTrue();
     }
 
@@ -396,6 +413,11 @@
             return super.getSeeAllRow();
         }
 
+        @Override
+        public ListBuilder.RowBuilder getWifiSliceItemRow(WifiSliceItem wifiSliceItem) {
+            return super.getWifiSliceItemRow(wifiSliceItem);
+        }
+
         public boolean hasCreateEthernetRow() {
             return mHasCreateEthernetRow;
         }