Snap for 8426163 from 0cafcaaffd9b9bd68dcafb4528dd3bcf8dfef1fc to mainline-tzdata2-release

Change-Id: I26c58f882e7a7a05cea58e31b6797517f280e27c
diff --git a/Android.bp b/Android.bp
index 6eeca34..83bdc35 100644
--- a/Android.bp
+++ b/Android.bp
@@ -23,7 +23,7 @@
     srcs: ["src/**/*.java"],
     sdk_version: "system_current",
     min_sdk_version: "29",
-    target_sdk_version: "30", // Keep in sync with CaptivePortalLoginTests
+    target_sdk_version: "30",
     static_libs: [
         "androidx.annotation_annotation",
         "androidx.legacy_legacy-support-v4",
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0ac691c..0b0c191 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -18,8 +18,8 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.captiveportallogin"
-    android:versionCode="319999900"
-    android:versionName="s_aml_319999900">
+    android:versionCode="309999900"
+    android:versionName="r_aml_309999900">
 
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
@@ -49,7 +49,6 @@
             android:name="com.android.captiveportallogin.CaptivePortalLoginActivity"
             android:label="@string/action_bar_label"
             android:theme="@style/AppTheme"
-            android:exported="true"
             android:configChanges="keyboardHidden|orientation|screenSize" >
             <intent-filter>
                 <action android:name="android.net.conn.CAPTIVE_PORTAL"/>
diff --git a/TEST_MAPPING b/TEST_MAPPING
index cd9448b..c2cd949 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,10 +1,10 @@
 {
-  "presubmit": [
+  "postsubmit": [
     {
       "name": "CaptivePortalLoginTests"
     }
   ],
-  "mainline-presubmit": [
+  "mainline-postsubmit": [
     {
       "name": "CaptivePortalLoginTests[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex]"
     }
diff --git a/src/com/android/captiveportallogin/DownloadService.java b/src/com/android/captiveportallogin/DownloadService.java
index e9569db..da8eb2c 100644
--- a/src/com/android/captiveportallogin/DownloadService.java
+++ b/src/com/android/captiveportallogin/DownloadService.java
@@ -430,7 +430,7 @@
                 .setIdentifier(String.valueOf(taskId));
 
         final PendingIntent pendingIntent = PendingIntent.getActivity(
-                this, 0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE);
+                this, 0 /* requestCode */, intent, 0 /* flags */);
         return new Notification.Builder(this, CHANNEL_DOWNLOADS)
                 .setContentTitle(getResources().getString(R.string.download_completed))
                 .setContentText(displayName)
diff --git a/tests/Android.bp b/tests/Android.bp
index d6f2a95..78b10c3 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -20,13 +20,10 @@
 
 android_test {
     name: "CaptivePortalLoginTests",
-    defaults: ["framework-connectivity-test-defaults"],
     srcs: ["src/**/*.java", "src/**/*.kt"],
     platform_apis: true,
     min_sdk_version: "29",
-    target_sdk_version: "30", // Keep in sync with CaptivePortalLogin
-    test_suites: ["general-tests"],
-    test_mainline_modules: ["CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex"],
+    test_suites: ["device-tests"],
 
     static_libs: [
         "androidx.test.rules",
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index b6f157f..a263944 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -18,6 +18,8 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.captiveportallogin.tests">
+    <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
+
     <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
 
     <application android:debuggable="true">
diff --git a/tests/src/com/android/captiveportallogin/CaptivePortalLoginActivityTest.java b/tests/src/com/android/captiveportallogin/CaptivePortalLoginActivityTest.java
index 4bf622e..3cd349a 100644
--- a/tests/src/com/android/captiveportallogin/CaptivePortalLoginActivityTest.java
+++ b/tests/src/com/android/captiveportallogin/CaptivePortalLoginActivityTest.java
@@ -27,7 +27,6 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
 import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
 
-import static androidx.lifecycle.Lifecycle.State.DESTROYED;
 import static androidx.test.espresso.intent.Intents.intending;
 import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction;
 import static androidx.test.espresso.intent.matcher.IntentMatchers.isInternal;
@@ -39,12 +38,12 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
 import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork;
-import static com.android.testutils.TestPermissionUtil.runAsShell;
 
 import static junit.framework.Assert.assertEquals;
 
 import static org.hamcrest.CoreMatchers.not;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 import static org.mockito.Mockito.any;
@@ -79,6 +78,7 @@
 
 import androidx.test.core.app.ActivityScenario;
 import androidx.test.espresso.intent.Intents;
+import androidx.test.espresso.intent.rule.IntentsTestRule;
 import androidx.test.espresso.web.webdriver.Locator;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SdkSuppress;
@@ -88,6 +88,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.MockitoAnnotations;
@@ -103,8 +104,6 @@
 import java.util.Map;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.BooleanSupplier;
 
 import fi.iki.elonen.NanoHTTPD;
@@ -122,8 +121,7 @@
             InetAddresses.parseNumericAddress("2001:db8::8"), 64);
     private static final String TEST_USERAGENT = "Test/42.0 Unit-test";
     private static final String TEST_FRIENDLY_NAME = "Network friendly name";
-    private static final String TEST_PORTAL_HOSTNAME = "localhost";
-    private ActivityScenario<InstrumentedCaptivePortalLoginActivity> mActivityScenario;
+    private InstrumentedCaptivePortalLoginActivity mActivity;
     private MockitoSession mSession;
     private Network mNetwork = new Network(TEST_NETID);
     private TestNetworkTracker mTestNetworkTracker;
@@ -135,9 +133,6 @@
     public static class InstrumentedCaptivePortalLoginActivity extends CaptivePortalLoginActivity {
         private final ConditionVariable mDestroyedCv = new ConditionVariable(false);
         private final CompletableFuture<Intent> mForegroundServiceStart = new CompletableFuture<>();
-        // Workaround for https://github.com/android/android-test/issues/1119
-        private final CompletableFuture<Intent> mOpenInBrowserIntent =
-                new CompletableFuture<>();
         @Override
         public Object getSystemService(String name) {
             switch (name) {
@@ -166,15 +161,8 @@
             mDestroyedCv.open();
         }
 
-        @Override
-        public void startActivity(Intent intent) {
-            if (Intent.ACTION_VIEW.equals(intent.getAction())
-                    && intent.getData() != null
-                    && intent.getData().getAuthority().startsWith(TEST_PORTAL_HOSTNAME)) {
-                mOpenInBrowserIntent.complete(intent);
-                return;
-            }
-            super.startActivity(intent);
+        void waitForDestroy(long timeoutMs) {
+            assertTrue("Activity not destroyed within timeout", mDestroyedCv.block(timeoutMs));
         }
     }
 
@@ -229,6 +217,11 @@
         };
     }
 
+    @Rule
+    public final IntentsTestRule mActivityRule =
+            new IntentsTestRule<>(InstrumentedCaptivePortalLoginActivity.class,
+                    false /* initialTouchMode */, false  /* launchActivity */);
+
     @Before
     public void setUp() throws Exception {
         final Context context = getInstrumentation().getContext();
@@ -277,68 +270,51 @@
 
     @After
     public void tearDown() throws Exception {
-        if (mActivityScenario != null) {
-            // Note this may sometimes block for 45 seconds until
-            // https://github.com/android/android-test/issues/676 is fixed
-            mActivityScenario.close();
-            Intents.release();
-        }
+        mActivityRule.finishActivity();
+        if (mActivity != null) mActivity.waitForDestroy(TEST_TIMEOUT_MS);
         getInstrumentation().getContext().getSystemService(ConnectivityManager.class)
                 .bindProcessToNetwork(null);
-        if (mTestNetworkTracker != null) {
-            runAsShell(MANAGE_TEST_NETWORKS, mTestNetworkTracker::teardown);
-        }
+        if (mTestNetworkTracker != null) mTestNetworkTracker.teardown();
         // finish mocking after the activity has terminated to avoid races on teardown.
         mSession.finishMocking();
     }
 
     private void initActivity(String url) {
-        final Context ctx = getInstrumentation().getContext();
-        mActivityScenario = ActivityScenario.launch(
-                new Intent(ctx, InstrumentedCaptivePortalLoginActivity.class)
-                        .setAction(ACTION_CAPTIVE_PORTAL_SIGN_IN)
-                        .putExtra(EXTRA_CAPTIVE_PORTAL_URL, url)
-                        .putExtra(EXTRA_NETWORK, mNetwork)
-                        .putExtra(EXTRA_CAPTIVE_PORTAL_USER_AGENT, TEST_USERAGENT)
-                        .putExtra(EXTRA_CAPTIVE_PORTAL, new MockCaptivePortal()));
-        mActivityScenario.onActivity(activity -> {
-            ctx.getSystemService(KeyguardManager.class).requestDismissKeyguard(activity, null);
-            // Dismiss dialogs or notification shade, so the test can interact with the activity.
-            activity.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
-        });
+        // onCreate will be triggered in launchActivity(). Handle mock objects after
+        // launchActivity() if any new mock objects. Activity launching flow will be
+        //  1. launchActivity()
+        //  2. onCreate()
+        //  3. end of launchActivity()
+        mActivity = (InstrumentedCaptivePortalLoginActivity) mActivityRule.launchActivity(
+            new Intent(ACTION_CAPTIVE_PORTAL_SIGN_IN)
+                .putExtra(EXTRA_CAPTIVE_PORTAL_URL, url)
+                .putExtra(EXTRA_NETWORK, mNetwork)
+                .putExtra(EXTRA_CAPTIVE_PORTAL_USER_AGENT, TEST_USERAGENT)
+                .putExtra(EXTRA_CAPTIVE_PORTAL, new MockCaptivePortal())
+        );
+        // Verify activity created successfully.
+        assertNotNull(mActivity);
+        getInstrumentation().getContext().getSystemService(KeyguardManager.class)
+                .requestDismissKeyguard(mActivity, null);
+        // Dismiss dialogs or notification shade, so that the test can interact with the activity.
+        mActivity.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
         getInstrumentation().waitForIdleSync();
-
-        // Initialize intent capturing after launching the activity to avoid capturing extra intents
-        Intents.init();
     }
 
     @Test
     public void testonCreateWithNullCaptivePortal() throws Exception {
-        final Context ctx = getInstrumentation().getContext();
-        final Intent intent = new Intent(ctx, InstrumentedCaptivePortalLoginActivity.class)
-                .setAction(ACTION_CAPTIVE_PORTAL_SIGN_IN)
-                .putExtra(EXTRA_CAPTIVE_PORTAL_URL, TEST_URL)
-                .putExtra(EXTRA_NETWORK, mNetwork)
-                .putExtra(EXTRA_CAPTIVE_PORTAL_USER_AGENT, TEST_USERAGENT)
-                .putExtra(EXTRA_CAPTIVE_PORTAL, (Bundle) null);
-        try (ActivityScenario<InstrumentedCaptivePortalLoginActivity> scenario =
-                     ActivityScenario.launch(intent)) {
-            getInstrumentation().waitForIdleSync();
-            // Verify that activity calls finish() immediately in its onCreate
-            assertEquals(DESTROYED, scenario.getState());
-        }
+        mActivity = (InstrumentedCaptivePortalLoginActivity) mActivityRule.launchActivity(
+                new Intent(ACTION_CAPTIVE_PORTAL_SIGN_IN)
+                    .putExtra(EXTRA_CAPTIVE_PORTAL_URL, TEST_URL)
+                    .putExtra(EXTRA_NETWORK, mNetwork)
+                    .putExtra(EXTRA_CAPTIVE_PORTAL_USER_AGENT, TEST_USERAGENT)
+                    .putExtra(EXTRA_CAPTIVE_PORTAL, (Bundle) null));
+        // Verify that activity is still created but waiting for closing.
+        assertNotNull(mActivity);
     }
 
-    /**
-     * Get the activity MockCaptivePortal.
-     *
-     * The activity may use a different MockCaptivePortal instance after being recreated, so the
-     * MockCaptivePortal should not be kept across possible activity recreation.
-     */
     private MockCaptivePortal getCaptivePortal() {
-        final AtomicReference<MockCaptivePortal> portalRef = new AtomicReference<>();
-        mActivityScenario.onActivity(a -> portalRef.set((MockCaptivePortal) a.mCaptivePortal));
-        return portalRef.get();
+        return (MockCaptivePortal) mActivity.mCaptivePortal;
     }
 
     private void configNonVpnNetwork() {
@@ -378,21 +354,19 @@
         initActivity(TEST_URL);
         // Test non-vpn case.
         configNonVpnNetwork();
-        mActivityScenario.onActivity(activity -> assertFalse(activity.hasVpnNetwork()));
-
+        assertFalse(mActivity.hasVpnNetwork());
         // Test vpn case.
         configVpnNetwork();
-        mActivityScenario.onActivity(activity -> assertTrue(activity.hasVpnNetwork()));
+        assertTrue(mActivity.hasVpnNetwork());
     }
 
     @Test
     public void testIsAlwaysOnVpnEnabled() throws Exception {
         initActivity(TEST_URL);
         doReturn(false).when(sMockDevicePolicyManager).isAlwaysOnVpnLockdownEnabled(any());
-        mActivityScenario.onActivity(activity -> assertFalse(activity.isAlwaysOnVpnEnabled()));
-
+        assertFalse(mActivity.isAlwaysOnVpnEnabled());
         doReturn(true).when(sMockDevicePolicyManager).isAlwaysOnVpnLockdownEnabled(any());
-        mActivityScenario.onActivity(activity -> assertTrue(activity.isAlwaysOnVpnEnabled()));
+        assertTrue(mActivity.isAlwaysOnVpnEnabled());
     }
 
     private void runVpnMsgOrLinkToBrowser(boolean useVpnMatcher) {
@@ -401,21 +375,18 @@
         configNonVpnNetwork();
         doReturn(false).when(sMockDevicePolicyManager).isAlwaysOnVpnLockdownEnabled(any());
         final String linkMatcher = ".*<a[^>]+href.*";
-        mActivityScenario.onActivity(act ->
-                assertTrue(act.getWebViewClient().getVpnMsgOrLinkToBrowser().matches(linkMatcher)));
+        assertTrue(mActivity.getWebViewClient().getVpnMsgOrLinkToBrowser().matches(linkMatcher));
 
         // Test has vpn case.
         configVpnNetwork();
         final String vpnMatcher = ".*<div.*vpnwarning.*";
-        mActivityScenario.onActivity(act ->
-                assertTrue(act.getWebViewClient().getVpnMsgOrLinkToBrowser().matches(vpnMatcher)));
+        assertTrue(mActivity.getWebViewClient().getVpnMsgOrLinkToBrowser().matches(vpnMatcher));
 
         // Test always-on vpn case.
         configNonVpnNetwork();
         doReturn(true).when(sMockDevicePolicyManager).isAlwaysOnVpnLockdownEnabled(any());
-        mActivityScenario.onActivity(act ->
-                assertTrue(act.getWebViewClient().getVpnMsgOrLinkToBrowser().matches(
-                        (useVpnMatcher ? vpnMatcher : linkMatcher))));
+        assertTrue(mActivity.getWebViewClient().getVpnMsgOrLinkToBrowser().matches(
+                (useVpnMatcher ? vpnMatcher : linkMatcher)));
     }
 
     @Test @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.Q)
@@ -436,20 +407,22 @@
     }
 
     private void notifyCapabilitiesChanged(final NetworkCapabilities nc) {
-        mActivityScenario.onActivity(a -> a.handleCapabilitiesChanged(mNetwork, nc));
+        mActivity.handleCapabilitiesChanged(mNetwork, nc);
         getInstrumentation().waitForIdleSync();
     }
 
-    private void notifyValidatedChangedAndDismissed(final NetworkCapabilities nc) {
-        // Get the MockCaptivePortal before the activity destroys itself
+    private void verifyDismissed() {
         final MockCaptivePortal cp = getCaptivePortal();
-        notifyCapabilitiesChanged(nc);
-
         assertEquals(cp.mDismissTimes, 1);
         assertEquals(cp.mIgnoreTimes, 0);
         assertEquals(cp.mUseTimes, 0);
     }
 
+    private void notifyValidatedChangedAndDismissed(final NetworkCapabilities nc) {
+        notifyCapabilitiesChanged(nc);
+        verifyDismissed();
+    }
+
     private void verifyNotDone() {
         final MockCaptivePortal cp = getCaptivePortal();
         assertEquals(cp.mDismissTimes, 0);
@@ -462,6 +435,13 @@
         verifyNotDone();
     }
 
+    private void verifyUseAsIs() {
+        final MockCaptivePortal cp = getCaptivePortal();
+        assertEquals(cp.mDismissTimes, 0);
+        assertEquals(cp.mIgnoreTimes, 0);
+        assertEquals(cp.mUseTimes, 1);
+    }
+
     private void setDismissPortalInValidatedNetwork(final boolean enable) {
         // Feature is enabled if the package version greater than configuration. Instead of reading
         // the package version, use Long.MAX_VALUE to replace disable configuration and 1 for
@@ -542,28 +522,17 @@
         final HttpServer server = runCustomSchemeTest("mailto:test@example.com");
         assertEquals(0, Intents.getIntents().size());
 
-        // Mockito intents cannot be used for an intent sent in onDestroy, due to
-        // https://github.com/android/android-test/issues/1119
-        final CompletableFuture<Intent> viewIntent = new CompletableFuture<>();
-        mActivityScenario.onActivity(a -> a.mOpenInBrowserIntent.thenAccept(viewIntent::complete));
-
-        final MockCaptivePortal cp = getCaptivePortal();
         onWebView().withElement(findElement(Locator.ID, "continue_link"))
                 .perform(webClick());
 
-        try {
-            viewIntent.get(TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
-        } catch (TimeoutException e) {
-            throw new AssertionError(
-                    "Open in browser intent not received after " + TEST_TIMEOUT_MS + "ms", e);
-        }
+        // The intent is sent in onDestroy(); there is no way to wait for that event, so poll
+        // until the intent is found.
+        assertTrue(isEventually(() -> Intents.getIntents().size() == 1, TEST_TIMEOUT_MS));
+        verifyUseAsIs();
+        final Intent sentIntent = Intents.getIntents().get(0);
+        assertEquals(Intent.ACTION_VIEW, sentIntent.getAction());
+        assertEquals(Uri.parse(server.makeUrl(TEST_URL_QUERY)), sentIntent.getData());
 
-        getInstrumentation().waitForIdleSync();
-        assertEquals(DESTROYED, mActivityScenario.getState());
-
-        assertEquals(cp.mDismissTimes, 0);
-        assertEquals(cp.mIgnoreTimes, 0);
-        assertEquals(cp.mUseTimes, 1);
         server.stop();
     }
 
@@ -585,6 +554,7 @@
         initActivity(server.makeUrl(TEST_URL_QUERY));
 
         // Create a mock file to be returned when mocking the file chooser
+        final Context ctx = mActivity.getApplicationContext();
         final Intent mockFileResponse = new Intent();
         final Uri mockFile = Uri.parse("content://mockdata");
         mockFileResponse.setData(mockFile);
@@ -608,10 +578,8 @@
         assertEquals(filename, fileIntent.getStringExtra(Intent.EXTRA_TITLE));
 
         // The download intent should be fired after the create file result is received
-        final CompletableFuture<Intent> dlIntentFuture = new CompletableFuture<>();
-        mActivityScenario.onActivity(a ->
-                a.mForegroundServiceStart.thenAccept(dlIntentFuture::complete));
-        final Intent dlIntent = dlIntentFuture.get(TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+        final Intent dlIntent = mActivity.mForegroundServiceStart.get(
+                TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
         assertEquals(DownloadService.class.getName(), dlIntent.getComponent().getClassName());
         assertEquals(mNetwork, dlIntent.getParcelableExtra(DownloadService.ARG_NETWORK));
         assertEquals(TEST_USERAGENT, dlIntent.getStringExtra(DownloadService.ARG_USERAGENT));
@@ -646,30 +614,26 @@
         initActivity("https://tc.example.com/");
 
         // Verify that the correct venue friendly name is used
-        mActivityScenario.onActivity(activity ->
-                assertEquals(getInstrumentation().getContext().getString(R.string.action_bar_title,
-                        TEST_FRIENDLY_NAME), activity.getActionBar().getTitle()));
+        assertEquals(getInstrumentation().getContext().getString(R.string.action_bar_title,
+                TEST_FRIENDLY_NAME), mActivity.getActionBar().getTitle());
     }
 
     @Test @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.Q)
     public void testWifiSsid_Q() throws Exception {
         configNonVpnNetwork();
         initActivity("https://portal.example.com/");
-        mActivityScenario.onActivity(activity ->
-                assertEquals(activity.getActionBar().getTitle(),
-                        getInstrumentation().getContext().getString(R.string.action_bar_title,
-                                TEST_WIFIINFO_SSID)));
-
+        assertEquals(mActivity.getActionBar().getTitle(),
+                getInstrumentation().getContext().getString(R.string.action_bar_title,
+                        TEST_WIFIINFO_SSID));
     }
 
     @Test @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
     public void testWifiSsid() throws Exception {
         configNonVpnNetwork();
         initActivity("https://portal.example.com/");
-        mActivityScenario.onActivity(activity ->
-                assertEquals(activity.getActionBar().getTitle(),
-                        getInstrumentation().getContext().getString(R.string.action_bar_title,
-                                TEST_NC_SSID)));
+        assertEquals(mActivity.getActionBar().getTitle(),
+                getInstrumentation().getContext().getString(R.string.action_bar_title,
+                        TEST_NC_SSID));
     }
 
     /**
@@ -728,7 +692,7 @@
 
         private HttpServer(ServerSocket socket) {
             // 0 as port for picking a port automatically
-            super(TEST_PORTAL_HOSTNAME, 0);
+            super("localhost", 0);
             mSocket = socket;
         }
 
@@ -740,7 +704,7 @@
         private String makeUrl(String query) {
             return new Uri.Builder()
                     .scheme("http")
-                    .encodedAuthority(TEST_PORTAL_HOSTNAME + ":" + mSocket.getLocalPort())
+                    .encodedAuthority("localhost:" + mSocket.getLocalPort())
                     // Explicitly specify an empty path to match the format of URLs returned by
                     // WebView (for example in onDownloadStart)
                     .path("/")
diff --git a/tests/src/com/android/captiveportallogin/DownloadServiceTest.kt b/tests/src/com/android/captiveportallogin/DownloadServiceTest.kt
index aba864a..7139e7c 100644
--- a/tests/src/com/android/captiveportallogin/DownloadServiceTest.kt
+++ b/tests/src/com/android/captiveportallogin/DownloadServiceTest.kt
@@ -54,6 +54,7 @@
 import java.net.URL
 import java.net.URLConnection
 import java.nio.charset.StandardCharsets
+import java.text.NumberFormat
 import java.util.concurrent.SynchronousQueue
 import java.util.concurrent.TimeUnit.MILLISECONDS
 import kotlin.math.min
@@ -287,6 +288,10 @@
         assertTrue(TEST_FILESIZE / 100 > 0)
         inputStream1.setAvailable(TEST_FILESIZE / 100)
 
+        // 1% progress should be shown in the notification
+        val progressText = NumberFormat.getPercentInstance().format(.01f)
+        findNotification(UiSelector().textContains(progressText))
+
         // Setup the connection for the next download with indeterminate progress
         val inputStream2 = TestInputStream()
         doReturn(inputStream2).`when`(connection).inputStream