Merge "Skip tests using notifications on TV"
diff --git a/Android.bp b/Android.bp
index 5be7de4..4a118cb 100644
--- a/Android.bp
+++ b/Android.bp
@@ -31,7 +31,6 @@
         "captiveportal-lib",
     ],
     manifest: "AndroidManifest.xml",
-    plugins: ["java_api_finder"],
     lint: { strict_updatability_linting: true },
     optimize: {
         ignore_warnings: false,
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index e2cd23b..b0baf18 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -6,7 +6,7 @@
     <string name="action_do_not_use_network" msgid="6324702363356892396">"Do not use this network"</string>
     <string name="action_bar_label" msgid="2023171629563754892">"Sign in to network"</string>
     <string name="action_bar_title" msgid="2566334512545554724">"Sign in to %1$s"</string>
-    <string name="ssl_error_warning" msgid="494203210316238046">"The network that you’re trying to join has security issues."</string>
+    <string name="ssl_error_warning" msgid="494203210316238046">"The network you’re trying to join has security issues."</string>
     <string name="ssl_error_example" msgid="4574594291839092653">"For example, the login page may not belong to the organization shown."</string>
     <string name="no_bypass_error_vpnwarning" msgid="5263739853101734851">"Additionally, it is not possible to bypass this error because the device is currently running a VPN."</string>
     <string name="error_continue_via_browser" msgid="7091550471744444659">"Continue anyway via browser"</string>
@@ -19,7 +19,7 @@
     <string name="ssl_error_unknown" msgid="3751419329218834886">"Unknown certificate error."</string>
     <string name="ssl_security_warning_title" msgid="7912335118289529802">"Security warning"</string>
     <string name="ssl_error_view_certificate" msgid="3447891108083278449">"View certificate"</string>
-    <string name="custom_scheme_warning" msgid="1809266150423969087">"The network that you are trying to join is requesting to open another application."</string>
+    <string name="custom_scheme_warning" msgid="1809266150423969087">"The network you are trying to join is requesting to open another application."</string>
     <string name="custom_scheme_example" msgid="7126568152528588592">"For example, the login page may require a specific application for authentication"</string>
     <string name="ok" msgid="6584612582120777209">"OK"</string>
     <string name="page_info_address" msgid="1290683284404217554">"Address:"</string>
@@ -27,7 +27,7 @@
     <string name="downloading_paramfile" msgid="685182551665849043">"Downloading %1$s"</string>
     <string name="download_completed" msgid="5430865338124330584">"Download completed"</string>
     <string name="error_downloading_paramfile" msgid="2431082160412515409">"Could not download %1$s"</string>
-    <string name="channel_name_downloads" msgid="8446786286617933444">"Download"</string>
+    <string name="channel_name_downloads" msgid="8446786286617933444">"Downloads"</string>
     <string name="channel_description_downloads" msgid="8751992699855833481">"Notifications showing completed or cancelled downloads"</string>
     <string name="channel_name_download_progress" msgid="6805362260479605374">"Download progress"</string>
     <string name="channel_description_download_progress" msgid="5788105841492070647">"Notifications showing the progress of file downloads"</string>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index 1b38521..bbeeb12 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -20,7 +20,7 @@
     <string name="ssl_security_warning_title" msgid="7912335118289529802">"सुरक्षासम्बन्धी चेतावनी"</string>
     <string name="ssl_error_view_certificate" msgid="3447891108083278449">"प्रमाणपत्र हेर्नुहोस्‌"</string>
     <string name="custom_scheme_warning" msgid="1809266150423969087">"तपाईं जोडिन खोजिरहनुभएको नेटवर्कले अर्को एप खोल्न अनुरोध गरिरहेको छ।"</string>
-    <string name="custom_scheme_example" msgid="7126568152528588592">"उदाहरणका लागि, लग इन पृष्ठले कुनै निश्चित अनुप्रयोगमार्फत परिचय प्रमाणित गर्न आवश्यकता जनाउन सक्छ"</string>
+    <string name="custom_scheme_example" msgid="7126568152528588592">"उदाहरणका लागि, लग इन पृष्ठले कुनै निश्चित एपमार्फत परिचय प्रमाणित गर्न आवश्यकता जनाउन सक्छ"</string>
     <string name="ok" msgid="6584612582120777209">"ठिक छ"</string>
     <string name="page_info_address" msgid="1290683284404217554">"ठेगाना:"</string>
     <string name="page_info" msgid="46593086046896385">"पृष्ठको जानकारी"</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 3586fba..bf0241e 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1,7 +1,9 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-
-    <string name="app_name">CaptivePortalLogin</string>
+    <!-- When the user connects to a network that has a captive portal (for example the login page
+    of some coffee shop wifi), the system uses an integrated app to show the user the login page.
+    This is the name of this app. It should be translated in each language (not used as-is). -->
+    <string name="app_name">Captive Portal Login</string>
     <string name="action_use_network">Use this network as is</string>
     <string name="action_do_not_use_network">Do not use this network</string>
     <string name="action_bar_label">Sign in to network</string>
diff --git a/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 8249543..64f7ce5 100755
--- a/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -115,8 +115,6 @@
     public static final String HTTP_LOCATION_HEADER_NAME = "Location";
     private static final String DEFAULT_CAPTIVE_PORTAL_HTTP_URL =
             "http://connectivitycheck.gstatic.com/generate_204";
-    public static final String DISMISS_PORTAL_IN_VALIDATED_NETWORK =
-            "dismiss_portal_in_validated_network";
     // This should match the FileProvider authority specified in the app manifest.
     private static final String FILE_PROVIDER_AUTHORITY =
             "com.android.captiveportallogin.fileprovider";
@@ -1205,7 +1203,7 @@
             if (mWifiManager == null) {
                 return null;
             }
-            final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+            final WifiInfo wifiInfo = getWifiConnectionInfo();
             return removeDoubleQuotes(wifiInfo.getSSID());
         }
 
@@ -1215,6 +1213,11 @@
         return removeDoubleQuotes(nc.getSsid());
     }
 
+    @VisibleForTesting
+    WifiInfo getWifiConnectionInfo() {
+        return mWifiManager.getConnectionInfo();
+    }
+
     private static String removeDoubleQuotes(String string) {
         if (string == null) return null;
         final int length = string.length();
diff --git a/tests/src/com/android/captiveportallogin/CaptivePortalLoginActivityTest.java b/tests/src/com/android/captiveportallogin/CaptivePortalLoginActivityTest.java
index 1829569..0bb48c4 100644
--- a/tests/src/com/android/captiveportallogin/CaptivePortalLoginActivityTest.java
+++ b/tests/src/com/android/captiveportallogin/CaptivePortalLoginActivityTest.java
@@ -47,6 +47,7 @@
 import static org.hamcrest.CoreMatchers.not;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.any;
@@ -76,7 +77,6 @@
 import android.net.NetworkCapabilities;
 import android.net.Uri;
 import android.net.wifi.WifiInfo;
-import android.net.wifi.WifiManager;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.ConditionVariable;
@@ -110,7 +110,6 @@
 import java.io.IOException;
 import java.lang.reflect.Method;
 import java.net.ServerSocket;
-import java.nio.charset.StandardCharsets;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
@@ -145,7 +144,6 @@
     private @Spy DownloadService mDownloadService = new DownloadService();
 
     private static ConnectivityManager sConnectivityManager;
-    private static WifiManager sMockWifiManager;
     private static DevicePolicyManager sMockDevicePolicyManager;
     private static DownloadService.DownloadServiceBinder sDownloadServiceBinder;
 
@@ -167,14 +165,17 @@
                     return sConnectivityManager;
                 case Context.DEVICE_POLICY_SERVICE:
                     return sMockDevicePolicyManager;
-                case Context.WIFI_SERVICE:
-                    return sMockWifiManager;
                 default:
                     return super.getSystemService(name);
             }
         }
 
         @Override
+        WifiInfo getWifiConnectionInfo() {
+            return makeWifiInfo();
+        }
+
+        @Override
         public ComponentName startForegroundService(Intent service) {
             assertTrue("Multiple foreground services were started during the test",
                     mForegroundServiceStart.complete(service));
@@ -283,7 +284,6 @@
     public void setUp() throws Exception {
         final Context context = getInstrumentation().getContext();
         sConnectivityManager = spy(context.getSystemService(ConnectivityManager.class));
-        sMockWifiManager = mock(WifiManager.class);
         sMockDevicePolicyManager = mock(DevicePolicyManager.class);
         sDownloadServiceBinder = mock(DownloadService.DownloadServiceBinder.class);
 
@@ -301,25 +301,24 @@
             automation.dropShellPermissionIdentity();
         }
         mNetwork = mTestNetworkTracker.getNetwork();
-
-        final WifiInfo testInfo = makeWifiInfo();
-        doReturn(testInfo).when(sMockWifiManager).getConnectionInfo();
     }
 
-    private static WifiInfo makeWifiInfo() throws Exception {
+    private static WifiInfo makeWifiInfo() {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
-            return new WifiInfo.Builder()
-                    .setSsid(TEST_WIFIINFO_SSID.getBytes(StandardCharsets.US_ASCII))
-                    .build();
+            fail("Only Q should be using WifiInfo; R+ gets the wifi SSID via NetworkCapabilities");
         }
 
         // WifiInfo did not have a builder before R. Use non-public APIs on Q to set SSID.
-        final WifiInfo info = WifiInfo.class.getConstructor().newInstance();
-        final Class<?> wifiSsidClass = Class.forName("android.net.wifi.WifiSsid");
-        final Object wifiSsid = wifiSsidClass.getMethod("createFromAsciiEncoded",
-                String.class).invoke(null, TEST_WIFIINFO_SSID);
-        WifiInfo.class.getMethod("setSSID", wifiSsidClass).invoke(info, wifiSsid);
-        return info;
+        try {
+            final WifiInfo info = WifiInfo.class.getConstructor().newInstance();
+            final Class<?> wifiSsidClass = Class.forName("android.net.wifi.WifiSsid");
+            final Object wifiSsid = wifiSsidClass.getMethod("createFromAsciiEncoded",
+                    String.class).invoke(null, TEST_WIFIINFO_SSID);
+            WifiInfo.class.getMethod("setSSID", wifiSsidClass).invoke(info, wifiSsid);
+            return info;
+        } catch (ReflectiveOperationException e) {
+            throw new AssertionError("Failed to create WifiInfo on Q", e);
+        }
     }
 
     @After
@@ -361,8 +360,7 @@
         Intents.init();
     }
 
-    // TODO (b/244275469): figure out why first test is slow to start and revert 10min timeout
-    @Test(timeout = 600_000L)
+    @Test
     public void testonCreateWithNullCaptivePortal() throws Exception {
         final Context ctx = getInstrumentation().getContext();
         final Intent intent = new Intent(ctx, InstrumentedCaptivePortalLoginActivity.class)
@@ -423,8 +421,7 @@
         doReturn(vpnCapabilities).when(sConnectivityManager).getNetworkCapabilities(network2);
     }
 
-    // TODO (b/244275469): figure out why first test is slow to start and revert 10min timeout
-    @Test(timeout = 600_000L)
+    @Test
     public void testHasVpnNetwork() throws Exception {
         initActivity(TEST_URL);
         // Test non-vpn case.
@@ -436,8 +433,7 @@
         mActivityScenario.onActivity(activity -> assertTrue(activity.hasVpnNetwork()));
     }
 
-    // TODO (b/244275469): figure out why first test is slow to start and revert 10min timeout
-    @Test(timeout = 600_000L)
+    @Test
     public void testIsAlwaysOnVpnEnabled() throws Exception {
         initActivity(TEST_URL);
         doReturn(false).when(sMockDevicePolicyManager).isAlwaysOnVpnLockdownEnabled(any());
@@ -470,8 +466,7 @@
                         (useVpnMatcher ? vpnMatcher : linkMatcher))));
     }
 
-    // TODO (b/244275469): figure out why first test is slow to start and revert 10min timeout
-    @Test(timeout = 600_000L) @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.Q)
+    @Test @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.Q)
     public void testVpnMsgOrLinkToBrowser_BeforeR() throws Exception {
         // Before Android R, CaptivePortalLogin cannot call isAlwaysOnVpnLockdownEnabled() due to
         // permission denied. So CaptivePortalLogin doesn't know the status of VPN always-on, and it
@@ -479,8 +474,7 @@
         runVpnMsgOrLinkToBrowser(false /* useVpnMatcher */);
     }
 
-    // TODO (b/244275469): figure out why first test is slow to start and revert 10min timeout
-    @Test(timeout = 600_000L) @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
+    @Test @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
     public void testVpnMsgOrLinkToBrowser() throws Exception {
         // After Android R(including), DevicePolicyManager allows the caller who has the
         // PERMISSION_MAINLINE_NETWORK_STACK can call the isAlwaysOnVpnLockdownEnabled() to get the
@@ -526,8 +520,7 @@
         }
     }
 
-    // TODO (b/244275469): figure out why first test is slow to start and revert 10min timeout
-    @Test(timeout = 600_000L) @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
+    @Test @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
     public void testNetworkCapabilitiesUpdate_RAndLater() throws Exception {
         initActivity(TEST_URL);
         // NetworkCapabilities updates w/o NET_CAPABILITY_VALIDATED.
@@ -544,8 +537,7 @@
         waitForDestroyedState();
     }
 
-    // TODO (b/244275469): figure out why first test is slow to start and revert 10min timeout
-    @Test(timeout = 600_000L) @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.Q)
+    @Test @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.Q)
     public void testNetworkCapabilitiesUpdate_Q() throws Exception {
         initActivity(TEST_URL);
         final NetworkCapabilities nc = new NetworkCapabilities();
@@ -570,8 +562,7 @@
         return server;
     }
 
-    // TODO (b/244275469): figure out why first test is slow to start and revert 10min timeout
-    @Test(timeout = 600_000L)
+    @Test
     public void testTelScheme() throws Exception {
         final String telUri = "tel:0123456789";
         final HttpServer server = runCustomSchemeTest(telUri);
@@ -583,8 +574,7 @@
         server.stop();
     }
 
-    // TODO (b/244275469): figure out why first test is slow to start and revert 10min timeout
-    @Test(timeout = 600_000L)
+    @Test
     public void testSmsScheme() throws Exception {
         final String telUri = "sms:0123456789";
         final HttpServer server = runCustomSchemeTest(telUri);
@@ -596,8 +586,7 @@
         server.stop();
     }
 
-    // TODO (b/244275469): figure out why first test is slow to start and revert 10min timeout
-    @Test(timeout = 600_000L)
+    @Test
     public void testUnsupportedScheme() throws Exception {
         final HttpServer server = runCustomSchemeTest("mailto:test@example.com");
         assertEquals(0, Intents.getIntents().size());
@@ -627,8 +616,7 @@
         server.stop();
     }
 
-    // TODO (b/244275469): figure out why first test is slow to start and revert 10min timeout
-    @Test(timeout = 600_000L)
+    @Test
     public void testDownload() throws Exception {
         // Setup the server with a single link on the portal page, leading to a download
         final HttpServer server = new HttpServer();
@@ -681,8 +669,7 @@
         server.stop();
     }
 
-    // TODO (b/244275469): figure out why first test is slow to start and revert 10min timeout
-    @Test(timeout = 600_000L)
+    @Test
     public void testVenueFriendlyNameTitle() throws Exception {
         assumeTrue(isAtLeastS());
         final LinkProperties linkProperties = new LinkProperties();
@@ -710,8 +697,7 @@
                         TEST_FRIENDLY_NAME), activity.getActionBar().getTitle()));
     }
 
-    // TODO (b/244275469): figure out why first test is slow to start and revert 10min timeout
-    @Test(timeout = 600_000L) @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.Q)
+    @Test @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.Q)
     public void testWifiSsid_Q() throws Exception {
         configNonVpnNetwork();
         initActivity("https://portal.example.com/");
@@ -722,8 +708,7 @@
 
     }
 
-    // TODO (b/244275469): figure out why first test is slow to start and revert 10min timeout
-    @Test(timeout = 600_000L) @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
+    @Test @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
     public void testWifiSsid() throws Exception {
         configNonVpnNetwork();
         initActivity("https://portal.example.com/");
@@ -887,8 +872,7 @@
         return messageFuture;
     }
 
-    // TODO (b/244275469): figure out why first test is slow to start and revert 10min timeout
-    @Test(timeout = 600_000L)
+    @Test
     public void testDirectlyOpen_onCreateDeleteFile() throws Exception {
         final String linkIdDownload = "download";
         final HttpServer server = prepareTestDirectlyOpen(linkIdDownload, "dl",
@@ -911,8 +895,7 @@
         server.stop();
     }
 
-    // TODO (b/244275469): figure out why first test is slow to start and revert 10min timeout
-    @Test(timeout = 600_000L)
+    @Test
     public void testDirectlyOpen_onDownloadAborted() throws Exception {
         initActivity(TEST_URL);
         final Uri mockFile = Uri.parse("content://mockdata");
@@ -927,8 +910,7 @@
 
     }
 
-    // TODO (b/244275469): figure out why first test is slow to start and revert 10min timeout
-    @Test(timeout = 600_000L)
+    @Test
     public void testDirectlyOpen_taskCancelToast() throws Exception {
         final String linkIdDownload = "download";
         final String expectMsg = getInstrumentation().getContext().getString(
@@ -947,8 +929,7 @@
         server.stop();
     }
 
-    // TODO (b/244275469): figure out why first test is slow to start and revert 10min timeout
-    @Test(timeout = 600_000L)
+    @Test
     public void testDirectlyOpen_cancelPendingTask() throws Exception {
         final String linkIdDownload = "download";
         final String downloadQuery = "dl";
@@ -983,8 +964,7 @@
         server.stop();
     }
 
-    // TODO (b/244275469): figure out why first test is slow to start and revert 10min timeout
-    @Test(timeout = 600_000L)
+    @Test
     public void testDirectlyOpen_successfullyDownload() throws Exception {
         final String linkIdDownload = "download";
         final String mimeType = TEST_WIFI_CONFIG_TYPE;