Merge "Add QUERY_AUDIO_STATE permission"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 350ddd6..f06d38f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1422,6 +1422,23 @@
         </activity>
 
         <activity
+            android:name="Settings$WifiScanningSettingsActivity"
+            android:label="@string/location_scanning_wifi_always_scanning_title"
+            android:icon="@drawable/ic_homepage_location"
+            android:exported="true"
+            android:permission="android.permission.CHANGE_WIFI_STATE"
+            android:configChanges="orientation|keyboardHidden|screenSize">
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.WIFI_SCANNING_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                       android:value="com.android.settings.location.WifiScanningFragment" />
+            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+                       android:value="true" />
+        </activity>
+
+        <activity
             android:name=".Settings$SecurityDashboardActivity"
             android:label="@string/security_settings_title"
             android:icon="@drawable/ic_homepage_security"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f6b0895..e860313 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -13410,6 +13410,9 @@
     <string name="default_active_sim_sms">SMS</string>
     <!-- Provider Model: summary of default mobile data. [CHAR LIMIT=50] -->
     <string name="default_active_sim_mobile_data">mobile data</string>
+    <!-- Provider Model: Message to describe "Wi-Fi scan always available feature" when Wi-Fi is off and Wi-Fi
+    scanning is on. To mark a link to bring the user to "scanning settings" screen. [CHAR LIMIT=NONE]-->
+    <string name="wifi_scan_notify_message">To improve device experience, apps and services can still scan for Wi\u2011Fi networks at any time, even when Wi\u2011Fi is off. This can be used, for example, to improve location-based features and services. You can change this in Wi\u2011Fi scanning settings. <annotation id="link">Change</annotation></string>
 
     <!-- Summary text separator for preferences including a short description
          (eg. "Connected / 5G"). [CHAR LIMIT=50] -->
diff --git a/res/xml/network_provider_settings.xml b/res/xml/network_provider_settings.xml
index 9cab924..2d211b5 100644
--- a/res/xml/network_provider_settings.xml
+++ b/res/xml/network_provider_settings.xml
@@ -81,4 +81,10 @@
     <com.android.settings.datausage.DataUsagePreference
         android:key="non_carrier_data_usage"
         android:title="@string/non_carrier_data_usage"/>
+
+    <com.android.settingslib.widget.FooterPreference
+        android:key="wifi_status_message_footer"
+        android:selectable="false"
+        settings:allowDividerAbove="false"
+        settings:searchable="false"/>
 </PreferenceScreen>
diff --git a/src/com/android/settings/IccLockSettings.java b/src/com/android/settings/IccLockSettings.java
index e89e84b..71eb0f2 100644
--- a/src/com/android/settings/IccLockSettings.java
+++ b/src/com/android/settings/IccLockSettings.java
@@ -587,6 +587,7 @@
                 .inflate(com.android.internal.R.layout.transient_notification, null);
         final TextView tv = (TextView) v.findViewById(com.android.internal.R.id.message);
         tv.setText(errorMessage);
+        tv.setSingleLine(false);
 
         final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
         final Configuration config = v.getContext().getResources().getConfiguration();
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index cb2cde4..da988f8 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -166,6 +166,7 @@
     public static class AppUsageAccessSettingsActivity extends SettingsActivity { /* empty */ }
     public static class LocationSettingsActivity extends SettingsActivity { /* empty */ }
     public static class ScanningSettingsActivity extends SettingsActivity { /* empty */ }
+    public static class WifiScanningSettingsActivity extends SettingsActivity { /* empty */ }
     public static class PrivacyDashboardActivity extends SettingsActivity { /* empty */ }
     public static class PrivacySettingsActivity extends SettingsActivity { /* empty */ }
     public static class FactoryResetActivity extends SettingsActivity {
diff --git a/src/com/android/settings/bluetooth/DevicePickerFragment.java b/src/com/android/settings/bluetooth/DevicePickerFragment.java
index 602b79b..e8adac0 100644
--- a/src/com/android/settings/bluetooth/DevicePickerFragment.java
+++ b/src/com/android/settings/bluetooth/DevicePickerFragment.java
@@ -107,6 +107,8 @@
     @Override
     public void onStart() {
         super.onStart();
+        mLocalManager.getCachedDeviceManager().clearNonBondedDevices();
+        removeAllDevices();
         addCachedDevices();
         mSelectedDevice = null;
         if (mScanAllowed) {
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 6d7626c..70852fe 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -113,6 +113,7 @@
 import com.android.settings.localepicker.LocaleListEditor;
 import com.android.settings.location.LocationServices;
 import com.android.settings.location.LocationSettings;
+import com.android.settings.location.WifiScanningFragment;
 import com.android.settings.network.MobileNetworkListFragment;
 import com.android.settings.network.NetworkDashboardFragment;
 import com.android.settings.network.NetworkProviderSettings;
@@ -202,6 +203,7 @@
             ProcessStatsUi.class.getName(),
             NotificationStation.class.getName(),
             LocationSettings.class.getName(),
+            WifiScanningFragment.class.getName(),
             PrivacyDashboardFragment.class.getName(),
             LocationServices.class.getName(),
             SecuritySettings.class.getName(),
diff --git a/src/com/android/settings/network/EraseEuiccDataDialogFragment.java b/src/com/android/settings/network/EraseEuiccDataDialogFragment.java
index 819d3b1..2c3847c 100644
--- a/src/com/android/settings/network/EraseEuiccDataDialogFragment.java
+++ b/src/com/android/settings/network/EraseEuiccDataDialogFragment.java
@@ -19,6 +19,7 @@
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.settings.SettingsEnums;
+import android.content.Context;
 import android.content.DialogInterface;
 import android.os.AsyncTask;
 import android.os.Bundle;
@@ -75,23 +76,24 @@
         }
 
         if (which == DialogInterface.BUTTON_POSITIVE) {
-            if (ConfirmationSimDeletionPredicate.getSingleton().test(getContext())) {
+            Context context = getContext();
+            if (ConfirmationSimDeletionPredicate.getSingleton().test(context)) {
                 // Create a "verify it's you" verification over keyguard
                 // when "erase" button been pressed.
                 // This might protect from erasing by some automation process.
-                WifiDppUtils.showLockScreen(getContext(), () -> runAsyncWipe());
+                WifiDppUtils.showLockScreen(context, () -> runAsyncWipe(context));
             } else {
-                runAsyncWipe();
+                runAsyncWipe(context);
             }
         }
     }
 
-    private void runAsyncWipe() {
+    private void runAsyncWipe(Context context) {
         AsyncTask.execute(new Runnable() {
             @Override
             public void run() {
                 RecoverySystem.wipeEuiccData(
-                        getContext(), PACKAGE_NAME_EUICC_DATA_MANAGEMENT_CALLBACK);
+                        context, PACKAGE_NAME_EUICC_DATA_MANAGEMENT_CALLBACK);
             }
         });
     }
diff --git a/src/com/android/settings/network/NetworkProviderSettings.java b/src/com/android/settings/network/NetworkProviderSettings.java
index 88211ad..8a4929a 100644
--- a/src/com/android/settings/network/NetworkProviderSettings.java
+++ b/src/com/android/settings/network/NetworkProviderSettings.java
@@ -61,7 +61,9 @@
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.datausage.DataUsagePreference;
 import com.android.settings.datausage.DataUsageUtils;
+import com.android.settings.location.WifiScanningFragment;
 import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.utils.AnnotationSpan;
 import com.android.settings.wifi.AddNetworkFragment;
 import com.android.settings.wifi.AddWifiNetworkPreference;
 import com.android.settings.wifi.ConfigureWifiEntryFragment;
@@ -79,6 +81,7 @@
 import com.android.settingslib.search.Indexable;
 import com.android.settingslib.search.SearchIndexable;
 import com.android.settingslib.utils.ThreadUtils;
+import com.android.settingslib.widget.FooterPreference;
 import com.android.settingslib.widget.LayoutPreference;
 import com.android.settingslib.wifi.LongPressWifiEntryPreference;
 import com.android.settingslib.wifi.WifiSavedConfigUtils;
@@ -132,6 +135,7 @@
     @VisibleForTesting
     static final String PREF_KEY_DATA_USAGE = "non_carrier_data_usage";
     private static final String PREF_KEY_RESET_INTERNET = "resetting_your_internet";
+    private static final String PREF_KEY_WIFI_STATUS_MESSAGE = "wifi_status_message_footer";
 
     private static final int REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER = 0;
 
@@ -231,6 +235,8 @@
     LayoutPreference mResetInternetPreference;
     @VisibleForTesting
     ConnectedEthernetNetworkController mConnectedEthernetNetworkController;
+    @VisibleForTesting
+    FooterPreference mWifiStatusMessagePreference;
 
     /**
      * Mobile networks list for provider model
@@ -305,6 +311,7 @@
         addNetworkMobileProviderController();
         addConnectedEthernetNetworkController();
         addWifiSwitchPreferenceController();
+        mWifiStatusMessagePreference = findPreference(PREF_KEY_WIFI_STATUS_MESSAGE);
     }
 
     private void updateAirplaneModeMsgPreference(boolean visible) {
@@ -717,6 +724,7 @@
 
         switch (wifiState) {
             case WifiManager.WIFI_STATE_ENABLED:
+                setWifiScanMessage(/* isWifiEnabled */ true);
                 updateWifiEntryPreferences();
                 break;
 
@@ -732,6 +740,7 @@
                 break;
 
             case WifiManager.WIFI_STATE_DISABLED:
+                setWifiScanMessage(/* isWifiEnabled */ false);
                 removeConnectedWifiEntryPreference();
                 removeWifiEntryPreference();
                 setAdditionalSettingsSummaries();
@@ -741,6 +750,34 @@
         }
     }
 
+    @VisibleForTesting
+    void setWifiScanMessage(boolean isWifiEnabled) {
+        final Context context = getContext();
+        if (context == null) {
+            return;
+        }
+        if (isWifiEnabled || !mWifiManager.isScanAlwaysAvailable()) {
+            mWifiStatusMessagePreference.setVisible(false);
+            return;
+        }
+        if (TextUtils.isEmpty(mWifiStatusMessagePreference.getTitle())) {
+            AnnotationSpan.LinkInfo info = new AnnotationSpan.LinkInfo(
+                AnnotationSpan.LinkInfo.DEFAULT_ANNOTATION,
+                v -> launchWifiScanningFragment());
+            CharSequence text = AnnotationSpan.linkify(
+                context.getText(R.string.wifi_scan_notify_message), info);
+            mWifiStatusMessagePreference.setTitle(text);
+        }
+        mWifiStatusMessagePreference.setVisible(true);
+    }
+
+    private void launchWifiScanningFragment() {
+        new SubSettingLauncher(getContext())
+            .setDestination(WifiScanningFragment.class.getName())
+            .setSourceMetricsCategory(SettingsEnums.SETTINGS_NETWORK_CATEGORY)
+            .launch();
+    }
+
     @Override
     public void onWifiEntriesChanged() {
         if (mIsWifiEntryListStale) {
diff --git a/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java b/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java
index 8e65605..5f20894 100644
--- a/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java
+++ b/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java
@@ -25,7 +25,6 @@
 import android.graphics.drawable.ShapeDrawable;
 import android.graphics.drawable.shapes.OvalShape;
 import android.os.Bundle;
-import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -52,7 +51,6 @@
 
 import com.google.common.collect.ImmutableMap;
 
-import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
@@ -180,8 +178,7 @@
 
         final TextView operatorName = view.findViewById(R.id.operator_name_value);
         mTelephonyManager = mTelephonyManager.createForSubscriptionId(mSubId);
-        final ServiceState serviceState = mTelephonyManager.getServiceState();
-        operatorName.setText(serviceState == null ? "" : serviceState.getOperatorAlphaLong());
+        operatorName.setText(info.getCarrierName());
 
         final TextView phoneTitle = view.findViewById(R.id.number_label);
         phoneTitle.setVisibility(info.isOpportunistic() ? View.GONE : View.VISIBLE);
diff --git a/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java b/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java
index 19b044b..e048849 100644
--- a/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java
@@ -67,6 +67,7 @@
 import com.android.settings.wifi.ConnectedWifiEntryPreference;
 import com.android.settings.wifi.WifiConfigController2;
 import com.android.settings.wifi.WifiDialog2;
+import com.android.settingslib.widget.FooterPreference;
 import com.android.settingslib.widget.LayoutPreference;
 import com.android.settingslib.wifi.LongPressWifiEntryPreference;
 import com.android.wifitrackerlib.WifiEntry;
@@ -144,6 +145,7 @@
         mNetworkProviderSettings.mAirplaneModeMsgPreference = mAirplaneModeMsgPreference;
         mNetworkProviderSettings.mAirplaneModeEnabler = mAirplaneModeEnabler;
         mNetworkProviderSettings.mInternetUpdater = mInternetUpdater;
+        mNetworkProviderSettings.mWifiStatusMessagePreference = new FooterPreference(mContext);
         doReturn(NetworkProviderSettings.PREF_KEY_CONNECTED_ACCESS_POINTS)
                 .when(mConnectedWifiEntryPreferenceCategory).getKey();
         mNetworkProviderSettings.mConnectedWifiEntryPreferenceCategory =
@@ -532,6 +534,35 @@
     }
 
     @Test
+    public void setWifiScanMessage_wifiOnScanOn_footerIsInvisible() {
+        when(mWifiManager.isScanAlwaysAvailable()).thenReturn(true);
+
+        mNetworkProviderSettings.setWifiScanMessage(/* isWifiEnabled */ true);
+
+        assertThat(mNetworkProviderSettings.mWifiStatusMessagePreference.isVisible()).isFalse();
+    }
+
+    @Test
+    public void setWifiScanMessage_wifiOffScanOn_footerIsVisible() {
+        when(mWifiManager.isScanAlwaysAvailable()).thenReturn(true);
+
+        mNetworkProviderSettings.setWifiScanMessage(/* isWifiEnabled */ false);
+
+        assertThat(mNetworkProviderSettings.mWifiStatusMessagePreference.isVisible()).isTrue();
+        assertThat(mNetworkProviderSettings.mWifiStatusMessagePreference.getTitle().length())
+                .isNotEqualTo(0);
+    }
+
+    @Test
+    public void setWifiScanMessage_wifiOffScanOff_footerIsInvisible() {
+        when(mWifiManager.isScanAlwaysAvailable()).thenReturn(false);
+
+        mNetworkProviderSettings.setWifiScanMessage(/* isWifiEnabled */ false);
+
+        assertThat(mNetworkProviderSettings.mWifiStatusMessagePreference.isVisible()).isFalse();
+    }
+
+    @Test
     @Config(shadows = ShadowPreferenceFragmentCompat.class)
     public void onStop_shouldRemoveCallbacks() {
         View fragmentView = mock(View.class);
diff --git a/tests/robotests/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragmentTest.java b/tests/robotests/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragmentTest.java
index 70b0598..ea440c7 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragmentTest.java
@@ -31,7 +31,6 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.graphics.Color;
-import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -73,8 +72,6 @@
     @Mock
     private TelephonyManager mTelephonyMgr;
     @Mock
-    private ServiceState mServiceState;
-    @Mock
     private SubscriptionManager mSubscriptionMgr;
     @Mock
     private SubscriptionInfo mSubscriptionInfo;
@@ -95,11 +92,9 @@
         stm.setTelephonyManagerForSubscriptionId(mSubscriptionId, mTelephonyMgr);
         when(mTelephonyMgr.createForSubscriptionId(anyInt())).thenReturn(mTelephonyMgr);
 
-        when(mTelephonyMgr.getServiceState()).thenReturn(mServiceState);
-        when(mServiceState.getOperatorAlphaLong()).thenReturn("fake carrier name");
-
         when(mSubscriptionInfo.getSubscriptionId()).thenReturn(mSubscriptionId);
         when(mSubscriptionInfo.getDisplayName()).thenReturn("test");
+        when(mSubscriptionInfo.getCarrierName()).thenReturn("fake carrier name");
         when(mSubscriptionMgr.setDisplayName(any(), anyInt(), anyInt())).thenReturn(0);
 
         mActivity = spy(Robolectric.buildActivity(FragmentActivity.class).setup().get());