Merge "Added tests for when FillResponse authentication dialog is canceled." into oc-dev
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java b/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java
index 3e2f207..5e0f7d6 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import android.app.Activity;
 import android.app.PendingIntent;
 import android.app.assist.AssistStructure;
 import android.autofillservice.cts.CannedFillResponse.CannedDataset;
@@ -48,7 +49,13 @@
     private static final SparseArray<CannedFillResponse> sResponses = new SparseArray<>();
     private static final ArrayList<PendingIntent> sPendingIntents = new ArrayList<>();
 
+    private static Object sLock = new Object();
+
+    // Guarded by sLock
+    private static int sResultCode;
+
     static void resetStaticState() {
+        setResultCode(RESULT_OK);
         sDatasets.clear();
         sResponses.clear();
         for (int i = 0; i < sPendingIntents.size(); i++) {
@@ -83,7 +90,8 @@
     private static IntentSender createSender(Context context, String extraName, int id) {
         final Intent intent = new Intent(context, AuthenticationActivity.class);
         intent.putExtra(extraName, id);
-        final PendingIntent pendingIntent = PendingIntent.getActivity(context, id, intent, 0);
+        final PendingIntent pendingIntent = PendingIntent.getActivity(context, id, intent,
+                PendingIntent.FLAG_UPDATE_CURRENT);
         sPendingIntents.add(pendingIntent);
         return pendingIntent.getIntentSender();
     }
@@ -104,6 +112,16 @@
         return data;
     }
 
+    /**
+     * Sets the value that's passed to {@link Activity#setResult(int, Intent)} when on
+     * {@link Activity#onCreate(Bundle)}.
+     */
+    public static void setResultCode(int resultCode) {
+        synchronized (sLock) {
+            sResultCode = resultCode;
+        }
+    }
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -133,7 +151,12 @@
         // Pass on the auth result
         final Intent intent = new Intent();
         intent.putExtra(AutofillManager.EXTRA_AUTHENTICATION_RESULT, result);
-        setResult(RESULT_OK, intent);
+        final int resultCode;
+        synchronized (sLock) {
+            resultCode = sResultCode;
+        }
+        Log.d(TAG, "Returning code " + resultCode);
+        setResult(resultCode, intent);
 
         // Done
         finish();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index c157b38..cfb7b0d 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -16,6 +16,8 @@
 
 package android.autofillservice.cts;
 
+import static android.app.Activity.RESULT_CANCELED;
+import static android.app.Activity.RESULT_OK;
 import static android.autofillservice.cts.CannedFillResponse.NO_RESPONSE;
 import static android.autofillservice.cts.Helper.ID_PASSWORD;
 import static android.autofillservice.cts.Helper.ID_PASSWORD_LABEL;
@@ -1264,6 +1266,15 @@
 
     @Test
     public void testFillResponseAuthBothFields() throws Exception {
+        fillResponseAuthBothFields(false);
+    }
+
+    @Test
+    public void testFillResponseAuthBothFieldsUserCancelsFirstAttempt() throws Exception {
+        fillResponseAuthBothFields(true);
+    }
+
+    private void fillResponseAuthBothFields(boolean cancelFirstAttempt) throws Exception {
         // Set service.
         enableService();
         final MyAutofillCallback callback = mActivity.registerCallback();
@@ -1298,29 +1309,49 @@
         sReplier.getNextFillRequest();
         final View username = mActivity.getUsername();
         callback.assertUiShownEvent(username);
-        sUiBot.assertShownByText("Tap to auth response");
+        sUiBot.assertDatasets("Tap to auth response");
 
         // Make sure UI is show on 2nd field as well
         final View password = mActivity.getPassword();
         mActivity.onPassword(View::requestFocus);
         callback.assertUiHiddenEvent(username);
         callback.assertUiShownEvent(password);
-        sUiBot.assertShownByText("Tap to auth response");
+        sUiBot.assertDatasets("Tap to auth response");
 
         // Now tap on 1st field to show it again...
         mActivity.onUsername(View::requestFocus);
         callback.assertUiHiddenEvent(password);
         callback.assertUiShownEvent(username);
-        sUiBot.selectByText("Tap to auth response");
-        callback.assertUiHiddenEvent(username);
-        sUiBot.assertNotShownByText("Tap to auth response");
+
+        if (cancelFirstAttempt) {
+            // Trigger the auth dialog, but emulate cancel.
+            AuthenticationActivity.setResultCode(RESULT_CANCELED);
+            sUiBot.selectDataset("Tap to auth response");
+            callback.assertUiHiddenEvent(username);
+            callback.assertUiShownEvent(username);
+            sUiBot.assertDatasets("Tap to auth response");
+
+            // Make sure it's still shown on other fields...
+            mActivity.onPassword(View::requestFocus);
+            callback.assertUiHiddenEvent(username);
+            callback.assertUiShownEvent(password);
+            sUiBot.assertDatasets("Tap to auth response");
+
+            // Tap on 1st field to show it again...
+            mActivity.onUsername(View::requestFocus);
+            callback.assertUiHiddenEvent(password);
+            callback.assertUiShownEvent(username);
+        }
 
         // ...and select it this time
+        AuthenticationActivity.setResultCode(RESULT_OK);
+        sUiBot.selectDataset("Tap to auth response");
+        callback.assertUiHiddenEvent(username);
         callback.assertUiShownEvent(username);
+        sUiBot.assertNotShownByText("Tap to auth response");
         sUiBot.selectDataset("Dataset");
         callback.assertUiHiddenEvent(username);
         sUiBot.assertNoDatasets();
-        sUiBot.assertNotShownByText("Tap to auth response");
 
         // Check the results.
         mActivity.assertAutoFilled();
@@ -1367,18 +1398,18 @@
         sReplier.getNextFillRequest();
         final View username = mActivity.getUsername();
         callback.assertUiShownEvent(username);
-        sUiBot.assertShownByText("Tap to auth response");
+        sUiBot.assertDatasets("Tap to auth response");
 
         // Make sure UI is not show on 2nd field
         mActivity.onPassword(View::requestFocus);
         callback.assertUiHiddenEvent(username);
-        sUiBot.assertNotShownByText("Tap to auth response");
+        sUiBot.assertNoDatasets();
         // Now tap on 1st field to show it again...
         mActivity.onUsername(View::requestFocus);
         callback.assertUiShownEvent(username);
 
         // ...and select it this time
-        sUiBot.selectByText("Tap to auth response");
+        sUiBot.selectDataset("Tap to auth response");
         callback.assertUiHiddenEvent(username);
         sUiBot.assertNotShownByText("Tap to auth response");
 
@@ -1386,7 +1417,6 @@
         sUiBot.selectDataset("Dataset");
         callback.assertUiHiddenEvent(username);
         sUiBot.assertNoDatasets();
-        sUiBot.assertNotShownByText("Tap to auth response");
 
         // Check the results.
         mActivity.assertAutoFilled();
@@ -1423,9 +1453,8 @@
         callback.assertUiShownEvent(username);
 
         // Select the authentication dialog.
-        sUiBot.selectByText("Tap to auth response");
+        sUiBot.selectDataset("Tap to auth response");
         callback.assertUiHiddenEvent(username);
-        sUiBot.assertNotShownByText("Tap to auth response");
         sUiBot.assertNoDatasets();
     }
 
@@ -1462,12 +1491,27 @@
         // Wait for onFill() before proceeding.
         sReplier.getNextFillRequest();
         final View username = mActivity.getUsername();
-
-        // Authenticate
         callback.assertUiShownEvent(username);
-        sUiBot.selectByText("Tap to auth dataset");
+        sUiBot.assertDatasets("Tap to auth dataset");
+
+        // Make sure UI is show on 2nd field as well
+        final View password = mActivity.getPassword();
+        mActivity.onPassword(View::requestFocus);
         callback.assertUiHiddenEvent(username);
-        sUiBot.assertNotShownByText("Tap to auth dataset");
+        callback.assertUiShownEvent(password);
+        sUiBot.assertDatasets("Tap to auth dataset");
+
+        // Now tap on 1st field to show it again...
+        mActivity.onUsername(View::requestFocus);
+        callback.assertUiHiddenEvent(password);
+        callback.assertUiShownEvent(username);
+        sUiBot.assertDatasets("Tap to auth dataset");
+
+        // ...and select it this time
+        AuthenticationActivity.setResultCode(RESULT_OK);
+        sUiBot.selectDataset("Tap to auth dataset");
+        callback.assertUiHiddenEvent(username);
+        sUiBot.assertNoDatasets();
 
         // Check the results.
         mActivity.assertAutoFilled();
@@ -1516,14 +1560,14 @@
 
         // Authenticate
         callback.assertUiShownEvent(username);
-        sUiBot.selectByText("Tap to auth dataset");
+        sUiBot.selectDataset("Tap to auth dataset");
         callback.assertUiHiddenEvent(username);
 
         // Select a dataset from the new response
         callback.assertUiShownEvent(username);
-        sUiBot.selectByText("Dataset");
+        sUiBot.selectDataset("Dataset");
         callback.assertUiHiddenEvent(username);
-        sUiBot.assertNotShownByText("Dataset");
+        sUiBot.assertNoDatasets();
 
         // Check the results.
         mActivity.assertAutoFilled();
@@ -1570,9 +1614,9 @@
 
         // Authenticate
         callback.assertUiShownEvent(username);
-        sUiBot.selectByText("Tap to auth dataset");
+        sUiBot.selectDataset("Tap to auth dataset");
         callback.assertUiHiddenEvent(username);
-        sUiBot.assertNotShownByText("Tap to auth dataset");
+        sUiBot.assertNoDatasets();
 
         // Check the results.
         mActivity.assertAutoFilled();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java
index b60840d..756b6e9 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java
@@ -2223,22 +2223,22 @@
 
         // Finally, autofill and check them.
         mActivity.focusCell(2, 1);
-        sUiBot.selectByText("Auth 2");
+        sUiBot.selectDataset("Auth 2");
         sUiBot.selectDataset("Partition 2");
         expectation2.assertAutoFilled();
 
         mActivity.focusCell(4, 1);
-        sUiBot.selectByText("Auth 4");
+        sUiBot.selectDataset("Auth 4");
         sUiBot.selectDataset("Partition 4");
         expectation4.assertAutoFilled();
 
         mActivity.focusCell(3, 1);
-        sUiBot.selectByText("Auth 3");
+        sUiBot.selectDataset("Auth 3");
         sUiBot.selectDataset("Partition 3");
         expectation3.assertAutoFilled();
 
         mActivity.focusCell(1, 1);
-        sUiBot.selectByText("Auth 1");
+        sUiBot.selectDataset("Auth 1");
         sUiBot.selectDataset("Partition 1");
         expectation1.assertAutoFilled();
     }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
index d1f01e1..987ddbe 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
@@ -152,6 +152,9 @@
 
     /**
      * Selects a view by text.
+     *
+     * <p><b>NOTE:</b> when selecting an option in dataset picker is shown, prefer
+     * {@link #selectDataset(String)}.
      */
     void selectByText(String name) {
         Log.v(TAG, "selectByText(): " + name);
@@ -161,7 +164,10 @@
     }
 
     /**
-     * Asserts a text is not shown.
+     * Asserts a text is shown.
+     *
+     * <p><b>NOTE:</b> when asserting the dataset picker is shown, prefer
+     * {@link #assertDatasets(String...)}.
      */
     public void assertShownByText(String text) {
         final UiObject2 object = waitForObject(By.text(text));
@@ -169,7 +175,10 @@
     }
 
     /**
-     * Asserts a text is now shown.
+     * Asserts a text is not shown.
+     *
+     * <p><b>NOTE:</b> when asserting the dataset picker is not shown, prefer
+     * {@link #assertNoDatasets()}.
      */
     public void assertNotShownByText(String text) {
         final UiObject2 uiObject = mDevice.findObject(By.text(text));