Settings: Network setup UI changes for SUW

Author: Michael Bestas <mkbestas@lineageos.org>
Date:   Tue Aug 24 01:18:55 2021 +0300

    Settings: Network setup UI changes for SUW

    Change-Id: Ic8e97b78f19e59fe108c7c3304dfe7e7f49020a9

Author: Erfan Abdi <erfangplus@gmail.com>
Date:   Sun Mar 6 01:58:11 2022 -0700

    Settings: Apply SUW button theming to WiFi page

    Change-Id: Iab5723f4654d372948de372cfd62587e8932d72c

Author: Alexander Koskovich <akoskovich@pm.me>
Date:   Fri Feb 2 07:09:07 2024 -0500

    Handle mobile data on internet page during setup

    Change-Id: Id00e9ef135cd2748376c69596979826e764e9185

Author: Michael Bestas <mkbestas@lineageos.org>
Date:   Sat Feb 17 18:59:41 2024 +0200

    Fix network SetupWizard theme issues

    Change-Id: I7649ecacb5a2dd0cb15ed9b1d05c28b44257bb54

Change-Id: Ic8e97b78f19e59fe108c7c3304dfe7e7f49020a9
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index ef45b1e..253d196 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -475,6 +475,17 @@
         </activity>
 
         <activity
+            android:name=".network.NetworkSetupActivity"
+            android:exported="true">
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.NETWORK_PROVIDER_SETUP" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+                android:value="true" />
+        </activity>
+
+        <activity
             android:name=".wifi.WifiPickerActivity"
             android:permission="android.permission.CHANGE_WIFI_STATE"
             android:exported="true">
diff --git a/res/drawable/ic_network_setup.xml b/res/drawable/ic_network_setup.xml
new file mode 100644
index 0000000..4944cbc
--- /dev/null
+++ b/res/drawable/ic_network_setup.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2021 The LineageOS 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">
+
+    <path
+        android:fillColor="?android:attr/colorPrimary"
+        android:pathData="M12,2A8,8 0 0,0 4,10C4,14.03 7,17.42 11,17.93V19H10A1,1 0 0,0 9,20H2V22H9A1,1 0 0,0 10,23H14A1,1 0 0,0 15,22H22V20H15A1,1 0 0,0 14,19H13V17.93C17,17.43 20,14.03 20,10A8,8 0 0,0 12,2M12,4C12,4 12.74,5.28 13.26,7H10.74C11.26,5.28 12,4 12,4M9.77,4.43C9.5,4.93 9.09,5.84 8.74,7H6.81C7.5,5.84 8.5,4.93 9.77,4.43M14.23,4.44C15.5,4.94 16.5,5.84 17.19,7H15.26C14.91,5.84 14.5,4.93 14.23,4.44M6.09,9H8.32C8.28,9.33 8.25,9.66 8.25,10C8.25,10.34 8.28,10.67 8.32,11H6.09C6.03,10.67 6,10.34 6,10C6,9.66 6.03,9.33 6.09,9M10.32,9H13.68C13.72,9.33 13.75,9.66 13.75,10C13.75,10.34 13.72,10.67 13.68,11H10.32C10.28,10.67 10.25,10.34 10.25,10C10.25,9.66 10.28,9.33 10.32,9M15.68,9H17.91C17.97,9.33 18,9.66 18,10C18,10.34 17.97,10.67 17.91,11H15.68C15.72,10.67 15.75,10.34 15.75,10C15.75,9.66 15.72,9.33 15.68,9M6.81,13H8.74C9.09,14.16 9.5,15.07 9.77,15.56C8.5,15.06 7.5,14.16 6.81,13M10.74,13H13.26C12.74,14.72 12,16 12,16C12,16 11.26,14.72 10.74,13M15.26,13H17.19C16.5,14.16 15.5,15.07 14.23,15.57C14.5,15.07 14.91,14.16 15.26,13Z" />
+</vector>
diff --git a/src/com/android/settings/network/NetworkProviderSettings.java b/src/com/android/settings/network/NetworkProviderSettings.java
index f14c32c..acde54c 100644
--- a/src/com/android/settings/network/NetworkProviderSettings.java
+++ b/src/com/android/settings/network/NetworkProviderSettings.java
@@ -36,16 +36,19 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.EventLog;
 import android.util.Log;
 import android.view.ContextMenu;
 import android.view.ContextMenu.ContextMenuInfo;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.Toast;
 
 import androidx.annotation.NonNull;
@@ -66,6 +69,7 @@
 import com.android.settings.datausage.DataUsagePreference;
 import com.android.settings.datausage.DataUsageUtils;
 import com.android.settings.location.WifiScanningFragment;
+import com.android.settings.network.MobileDataEnabledListener;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.wifi.AddNetworkFragment;
 import com.android.settings.wifi.AddWifiNetworkPreference;
@@ -93,6 +97,10 @@
 import com.android.wifitrackerlib.WifiEntry.ConnectCallback;
 import com.android.wifitrackerlib.WifiPickerTracker;
 
+import com.google.android.setupcompat.template.FooterButtonStyleUtils;
+import com.google.android.setupcompat.util.WizardManagerHelper;
+import com.google.android.setupdesign.GlifPreferenceLayout;
+
 import java.util.List;
 import java.util.Optional;
 
@@ -105,7 +113,8 @@
 public class NetworkProviderSettings extends RestrictedSettingsFragment
         implements Indexable, WifiPickerTracker.WifiPickerTrackerCallback,
         WifiDialog2.WifiDialog2Listener, DialogInterface.OnDismissListener,
-        AirplaneModeEnabler.OnAirplaneModeChangedListener, InternetUpdater.InternetChangeListener {
+        AirplaneModeEnabler.OnAirplaneModeChangedListener, InternetUpdater.InternetChangeListener,
+        MobileDataEnabledListener.Client {
 
     public static final String ACTION_NETWORK_PROVIDER_SETTINGS =
             "android.settings.NETWORK_PROVIDER_SETTINGS";
@@ -168,6 +177,8 @@
     // Enable the Next button when a Wi-Fi network is connected.
     private boolean mEnableNextOnConnection;
 
+    private boolean mIsInSetupWizard;
+
     // This string extra specifies a network to open the connect dialog on, so the user can enter
     // network credentials.  This is used by quick settings for secured networks, among other
     // things.
@@ -199,6 +210,9 @@
     protected WifiManager mWifiManager;
     private WifiManager.ActionListener mSaveListener;
 
+    int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+    MobileDataEnabledListener mDataStateListener;
+
     protected InternetResetHelper mInternetResetHelper;
 
     /**
@@ -262,6 +276,7 @@
 
     public NetworkProviderSettings() {
         super(DISALLOW_CONFIG_WIFI);
+        mSubId = SubscriptionManager.getActiveDataSubscriptionId();
     }
 
     @Override
@@ -272,6 +287,18 @@
             return;
         }
 
+        if (mIsInSetupWizard) {
+            GlifPreferenceLayout layout = (GlifPreferenceLayout) view;
+            layout.setDividerInsets(Integer.MAX_VALUE, 0);
+
+            layout.setIcon(getContext().getDrawable(R.drawable.ic_network_setup));
+            layout.setHeaderText(R.string.provider_internet_settings);
+            FooterButtonStyleUtils.applyPrimaryButtonPartnerResource(activity, getNextButton(),
+                    true);
+
+            return;
+        }
+
         setPinnedHeaderView(com.android.settingslib.widget.progressbar.R.layout.progress_header);
         setProgressBarVisible(false);
 
@@ -295,6 +322,7 @@
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         mAirplaneModeEnabler = new AirplaneModeEnabler(getContext(), this);
+        mDataStateListener = new MobileDataEnabledListener(getContext(), this);
 
         // TODO(b/37429702): Add animations and preference comparator back after initial screen is
         // loaded (ODR).
@@ -342,6 +370,8 @@
                 fixConnectivityItem.setVisible(!mIsGuest && (!isAirplaneModeOn || isWifiEnabled));
             }
         };
+        final Intent intent = this.getIntent();
+        mIsInSetupWizard = WizardManagerHelper.isAnySetupWizard(intent);
     }
 
     private void updateUserType() {
@@ -351,6 +381,17 @@
         mIsGuest = userManager.isGuestUser();
     }
 
+    @Override
+    public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
+            Bundle savedInstanceState) {
+        if (mIsInSetupWizard) {
+            GlifPreferenceLayout layout = (GlifPreferenceLayout) parent;
+            return layout.onCreateRecyclerView(inflater, parent, savedInstanceState);
+        } else {
+            return super.onCreateRecyclerView(inflater, parent, savedInstanceState);
+        }
+    }
+
     private void addPreferences() {
         addPreferencesFromResource(R.xml.network_provider_settings);
 
@@ -462,6 +503,11 @@
             }
         };
 
+        if (mIsInSetupWizard) {
+            mConfigureWifiSettingsPreference.setVisible(false);
+            mDataUsagePreference.setVisible(false);
+        }
+
         if (savedInstanceState != null) {
             mDialogMode = savedInstanceState.getInt(SAVE_DIALOG_MODE);
             mDialogWifiEntryKey = savedInstanceState.getString(SAVE_DIALOG_WIFIENTRY_KEY);
@@ -501,6 +547,7 @@
             return;
         }
         mAirplaneModeEnabler.start();
+        mDataStateListener.start(mSubId);
     }
 
     private void restrictUi() {
@@ -529,7 +576,8 @@
         }
 
         changeNextButtonState(mWifiPickerTracker != null
-                && mWifiPickerTracker.getConnectedWifiEntry() != null);
+                && mWifiPickerTracker.getConnectedWifiEntry() != null
+                || getDataEnabled());
     }
 
     @Override
@@ -538,6 +586,7 @@
         getView().removeCallbacks(mUpdateWifiEntryPreferencesRunnable);
         getView().removeCallbacks(mHideProgressBarRunnable);
         mAirplaneModeEnabler.stop();
+        mDataStateListener.stop();
         super.onStop();
     }
 
@@ -916,7 +965,8 @@
             setProgressBarVisible(false);
         }
         changeNextButtonState(mWifiPickerTracker != null
-                && mWifiPickerTracker.getConnectedWifiEntry() != null);
+                && mWifiPickerTracker.getConnectedWifiEntry() != null
+                || getDataEnabled());
 
         // Edit the Wi-Fi network of specified SSID.
         if (mOpenSsid != null && mWifiPickerTracker != null) {
@@ -991,7 +1041,9 @@
 
                 if (mClickedConnect) {
                     mClickedConnect = false;
-                    scrollToPreference(connectedWifiPreferenceCategory);
+                    if (!mIsInSetupWizard) {
+                        scrollToPreference(connectedWifiPreferenceCategory);
+                    }
                 }
             }
         } else {
@@ -1112,10 +1164,12 @@
 
     @VisibleForTesting
     void setAdditionalSettingsSummaries() {
-        mConfigureWifiSettingsPreference.setSummary(getString(
-                isWifiWakeupEnabled()
-                        ? R.string.wifi_configure_settings_preference_summary_wakeup_on
-                        : R.string.wifi_configure_settings_preference_summary_wakeup_off));
+        if (!mIsInSetupWizard) {
+            mConfigureWifiSettingsPreference.setSummary(getString(
+                    isWifiWakeupEnabled()
+                            ? R.string.wifi_configure_settings_preference_summary_wakeup_on
+                            : R.string.wifi_configure_settings_preference_summary_wakeup_off));
+        }
 
         final int numSavedNetworks = mWifiPickerTracker == null ? 0 :
                 mWifiPickerTracker.getNumSavedNetworks();
@@ -1163,7 +1217,9 @@
     }
 
     protected void setProgressBarVisible(boolean visible) {
-        showPinnedHeader(visible);
+        if (!mIsInSetupWizard) {
+            showPinnedHeader(visible);
+        }
     }
 
     @VisibleForTesting
@@ -1197,7 +1253,7 @@
      * Renames/replaces "Next" button when appropriate. "Next" button usually exists in
      * Wi-Fi setup screens, not in usual wifi settings screen.
      *
-     * @param enabled true when the device is connected to a wifi network.
+     * @param enabled true when the device is connected to a mobile or wifi network.
      */
     @VisibleForTesting
     void changeNextButtonState(boolean enabled) {
@@ -1467,6 +1523,17 @@
     }
 
     /**
+     * Implementation of {@code MobileDataEnabledListener.Client}
+     */
+    public void onMobileDataEnabledChange() {
+        changeNextButtonState(getDataEnabled());
+    }
+
+    boolean getDataEnabled() {
+        return getContext().getSystemService(TelephonyManager.class).getDataEnabled(mSubId);
+    }
+
+    /**
      * A Wi-Fi preference for the connected Wi-Fi network without internet access.
      *
      * Override the icon color attribute by {@link ConnectedWifiEntryPreference#getIconColorAttr()}
diff --git a/src/com/android/settings/network/NetworkSetupActivity.java b/src/com/android/settings/network/NetworkSetupActivity.java
new file mode 100644
index 0000000..3b5fb82
--- /dev/null
+++ b/src/com/android/settings/network/NetworkSetupActivity.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2021-2024 The LineageOS 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 android.content.Intent;
+import android.content.res.Resources;
+import android.os.Bundle;
+
+import androidx.preference.PreferenceFragmentCompat;
+
+import com.android.settings.ButtonBarHandler;
+import com.android.settings.network.NetworkProviderSettings;
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.SetupWizardUtils;
+import com.android.settings.wifi.p2p.WifiP2pSettings;
+import com.android.settings.wifi.savedaccesspoints2.SavedAccessPointsWifiSettings2;
+
+import com.google.android.setupdesign.util.ThemeHelper;
+
+public class NetworkSetupActivity extends SettingsActivity implements ButtonBarHandler {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setTheme(SetupWizardUtils.getTheme(this, getIntent()));
+        setTheme(R.style.SettingsPreferenceTheme_SetupWizard);
+        ThemeHelper.trySetDynamicColor(this);
+        findViewById(R.id.content_parent).setFitsSystemWindows(false);
+    }
+
+    @Override
+    public Intent getIntent() {
+        Intent modIntent = new Intent(super.getIntent());
+        if (!modIntent.hasExtra(EXTRA_SHOW_FRAGMENT)) {
+            modIntent.putExtra(EXTRA_SHOW_FRAGMENT, getNetworkProviderSettingsClass().getName());
+            modIntent.putExtra(EXTRA_SHOW_FRAGMENT_TITLE_RESID,
+                    R.string.provider_internet_settings);
+        }
+        return modIntent;
+    }
+
+    @Override
+    protected boolean isValidFragment(String fragmentName) {
+        final boolean isSavedAccessPointsWifiSettings =
+                SavedAccessPointsWifiSettings2.class.getName().equals(fragmentName);
+
+        if (NetworkProviderSettings.class.getName().equals(fragmentName)
+                || WifiP2pSettings.class.getName().equals(fragmentName)
+                || isSavedAccessPointsWifiSettings) {
+            return true;
+        }
+        return false;
+    }
+
+    /* package */ Class<? extends PreferenceFragmentCompat> getNetworkProviderSettingsClass() {
+        return NetworkProviderSettings.class;
+    }
+}
diff --git a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
index 06015d4..6d74a5c 100644
--- a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
+++ b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
@@ -20,6 +20,7 @@
 import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
 
 import android.content.Context;
+import android.provider.Settings;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
@@ -40,6 +41,8 @@
 import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity;
 import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
 
+import com.google.android.setupcompat.util.WizardManagerHelper;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -121,6 +124,14 @@
     public boolean setChecked(boolean isChecked) {
         mNeedDialog = isDialogNeeded();
 
+        // If we are still provisioning we need to allow enabling mobile data first.
+        // By default it is not allowed to use mobile network during provisioning so
+        // we need to allow it.
+        if (!WizardManagerHelper.isDeviceProvisioned(mContext)) {
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED, isChecked ? 1 : 0);
+        }
+
         if (!mNeedDialog) {
             // Update data directly if we don't need dialog
             MobileNetworkUtils.setMobileDataEnabled(mContext, mSubId, isChecked, false);