Merge "Modify dialog message for partial connectivity"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 5c0256b..0271c92 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -348,7 +348,7 @@
                   android:clearTaskOnLaunch="true"
                   android:excludeFromRecents="true"
                   android:exported="true"
-                  android:permission="android.permission.CONNECTIVITY_INTERNAL"
+                  android:permission="android.permission.NETWORK_STACK"
                   android:taskAffinity=""
                   android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert">
             <intent-filter>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 8790dcb..44e26c3 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2040,6 +2040,8 @@
 
     <!-- Dialog text to tell the user that the selected network does not have Internet access. -->
     <string name="no_internet_access_text">This network has no internet access. Stay connected?</string>
+    <!-- Dialog text to tell the user that the selected network has incomplete Internet access. [CHAR LIMIT=100] -->
+    <string name="partial_connectivity_text">Some apps and services may not work due to limited connectivity. Use anyway?</string>
     <string name="no_internet_access_remember">Don\u2019t ask again for this network</string>
 
     <!-- Dialog text to tell the user that the selected network has lost Internet access, and asking the user whether they want to avoid this network. -->
diff --git a/src/com/android/settings/wifi/WifiNoInternetDialog.java b/src/com/android/settings/wifi/WifiNoInternetDialog.java
index b175665..e641f2c 100644
--- a/src/com/android/settings/wifi/WifiNoInternetDialog.java
+++ b/src/com/android/settings/wifi/WifiNoInternetDialog.java
@@ -38,6 +38,7 @@
 import com.android.settings.R;
 
 import static android.net.ConnectivityManager.ACTION_PROMPT_LOST_VALIDATION;
+import static android.net.ConnectivityManager.ACTION_PROMPT_PARTIAL_CONNECTIVITY;
 import static android.net.ConnectivityManager.ACTION_PROMPT_UNVALIDATED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
 
@@ -53,8 +54,9 @@
     private String mAction;
 
     private boolean isKnownAction(Intent intent) {
-        return intent.getAction().equals(ACTION_PROMPT_UNVALIDATED) ||
-                intent.getAction().equals(ACTION_PROMPT_LOST_VALIDATION);
+        return intent.getAction().equals(ACTION_PROMPT_UNVALIDATED)
+                || intent.getAction().equals(ACTION_PROMPT_LOST_VALIDATION)
+                || intent.getAction().equals(ACTION_PROMPT_PARTIAL_CONNECTIVITY);
     }
 
     @Override
@@ -131,6 +133,11 @@
             ap.mMessage = getString(R.string.no_internet_access_text);
             ap.mPositiveButtonText = getString(R.string.yes);
             ap.mNegativeButtonText = getString(R.string.no);
+        } else if (ACTION_PROMPT_PARTIAL_CONNECTIVITY.equals(mAction)) {
+            ap.mTitle = mNetworkName;
+            ap.mMessage = getString(R.string.partial_connectivity_text);
+            ap.mPositiveButtonText = getString(R.string.yes);
+            ap.mNegativeButtonText = getString(R.string.no);
         } else {
             ap.mTitle = getString(R.string.lost_internet_access_title);
             ap.mMessage = getString(R.string.lost_internet_access_text);
@@ -146,7 +153,8 @@
         ap.mView = checkbox;
         mAlwaysAllow = (CheckBox) checkbox.findViewById(com.android.internal.R.id.alwaysUse);
 
-        if (ACTION_PROMPT_UNVALIDATED.equals(mAction)) {
+        if (ACTION_PROMPT_UNVALIDATED.equals(mAction)
+                || ACTION_PROMPT_PARTIAL_CONNECTIVITY.equals(mAction)) {
             mAlwaysAllow.setText(getString(R.string.no_internet_access_remember));
         } else {
             mAlwaysAllow.setText(getString(R.string.lost_internet_access_persist));
@@ -174,6 +182,11 @@
             final boolean accept = (which == BUTTON_POSITIVE);
             action = (accept ? "Connect" : "Ignore");
             mCM.setAcceptUnvalidated(mNetwork, accept, always);
+        } else if (ACTION_PROMPT_PARTIAL_CONNECTIVITY.equals(mAction)) {
+            what = "PARTIAL_CONNECTIVITY";
+            final boolean accept = (which == BUTTON_POSITIVE);
+            action = (accept ? "Connect" : "Ignore");
+            mCM.setAcceptPartialConnectivity(mNetwork, accept, always);
         } else {
             what = "LOST_INTERNET";
             final boolean avoid = (which == BUTTON_POSITIVE);
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index fda5ce4..dece927 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -16,6 +16,7 @@
 package com.android.settings.wifi.details;
 
 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 
@@ -192,12 +193,14 @@
 
         @Override
         public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) {
-            // If the network just validated or lost Internet access, refresh network state.
-            // Don't do this on every NetworkCapabilities change because refreshNetworkState
-            // sends IPCs to the system server from the UI thread, which can cause jank.
+            // If the network just validated or lost Internet access or detected partial internet
+            // connectivity, refresh network state. Don't do this on every NetworkCapabilities
+            // change because refreshNetworkState sends IPCs to the system server from the UI
+            // thread, which can cause jank.
             if (network.equals(mNetwork) && !nc.equals(mNetworkCapabilities)) {
-                if (hasCapabilityChanged(nc, NET_CAPABILITY_VALIDATED) ||
-                        hasCapabilityChanged(nc, NET_CAPABILITY_CAPTIVE_PORTAL)) {
+                if (hasCapabilityChanged(nc, NET_CAPABILITY_VALIDATED)
+                        || hasCapabilityChanged(nc, NET_CAPABILITY_CAPTIVE_PORTAL)
+                        || hasCapabilityChanged(nc, NET_CAPABILITY_PARTIAL_CONNECTIVITY)) {
                     refreshNetworkState();
                 }
                 mNetworkCapabilities = nc;
diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
index 435882b..d5fd48e 100644
--- a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
@@ -622,6 +622,19 @@
         nc.removeCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
         updateNetworkCapabilities(nc);
         inOrder.verify(mockHeaderController).setSummary(summary);
+
+        // UI will be refreshed when device connects to a partial connectivity network.
+        summary = "Limited connection";
+        when(mockAccessPoint.getSettingsSummary()).thenReturn(summary);
+        nc.addCapability(NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY);
+        updateNetworkCapabilities(nc);
+        inOrder.verify(mockHeaderController).setSummary(summary);
+
+        // Although UI will be refreshed when network become validated. The Settings should
+        // continue to display "Limited connection" if network still provides partial connectivity.
+        nc.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
+        updateNetworkCapabilities(nc);
+        inOrder.verify(mockHeaderController).setSummary(summary);
     }
 
     @Test