Autofill: Add API for virtual view visibility - CTS

Test: added VirtualContainerActivityTest

bug:38509603

Change-Id: I81249fc45e3341ab2ed095fea312479a52f89329
diff --git a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivity.java b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivity.java
index 82bf213..7ec1114 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivity.java
@@ -53,7 +53,7 @@
 
         setContentView(R.layout.virtual_container_activity);
 
-        mCustomView = (VirtualContainerView) findViewById(R.id.virtual_container_view);
+        mCustomView = findViewById(R.id.virtual_container_view);
 
         mUsername = mCustomView.addLine(ID_USERNAME_LABEL, "Username", ID_USERNAME, BLANK_VALUE);
         mPassword = mCustomView.addLine(ID_PASSWORD_LABEL, "Password", ID_PASSWORD, BLANK_VALUE);
diff --git a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
index f5e6832..df2c79e 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
@@ -36,6 +36,8 @@
 import android.autofillservice.cts.InstrumentedAutoFillService.FillRequest;
 import android.autofillservice.cts.VirtualContainerView.Line;
 import android.graphics.Rect;
+import android.os.SystemClock;
+import android.service.autofill.SaveInfo;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.uiautomator.UiObject2;
 import android.view.autofill.AutofillManager;
@@ -45,6 +47,9 @@
 import org.junit.Rule;
 import org.junit.Test;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 /**
  * Test case for an activity containing virtual children.
  */
@@ -369,6 +374,43 @@
         sUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_PASSWORD);
     }
 
+    @Test
+    public void testSaveDialogShownWhenAllVirtualViewsNotVisible() throws Exception {
+        // Set service.
+        enableService();
+
+        // Set expectations.
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
+                .setFlags(SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE)
+                .build());
+
+        final CountDownLatch latch = new CountDownLatch(1);
+
+        // Trigger auto-fill.
+        mActivity.runOnUiThread(() -> {
+            mActivity.mUsername.changeFocus(true);
+            latch.countDown();
+        });
+        latch.await(Helper.UI_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+        sReplier.getNextFillRequest();
+
+        // TODO: 63602573 Should be removed once this bug is fixed
+        SystemClock.sleep(1000);
+
+        mActivity.runOnUiThread(() -> {
+            // Fill in some stuff
+            mActivity.mUsername.setText("foo");
+            mActivity.mPassword.setText("bar");
+
+            // Hide all virtual views
+            mActivity.mUsername.changeVisibility(false);
+            mActivity.mPassword.changeVisibility(false);
+        });
+
+        // Make sure save is shown
+        sUiBot.assertSaveShowing(SAVE_DATA_TYPE_PASSWORD);
+    }
 
     /**
      * Asserts the dataset picker is properly displayed in a give line.
diff --git a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java
index aa5d67b..e10c4ff 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java
@@ -125,6 +125,9 @@
         for (int i = 0; i < mLines.size(); i++) {
             x = mLeftMargin;
             final Line line = mLines.get(i);
+            if (!line.visible) {
+                continue;
+            }
             Log.v(TAG, "Drawing '" + line + "' at " + x + "x" + y);
             mTextPaint.setColor(line.focused ? mFocusedColor : mUnfocusedColor);
             final String readOnlyText = line.label.text + ":  [";
@@ -260,6 +263,7 @@
         final Rect bounds = new Rect();
 
         private boolean focused;
+        private boolean visible = true;
 
         private Line(String labelId, String label, String textId, String text) {
             this.label = new Item(this, ++nextId, labelId, label, false, false);
@@ -278,6 +282,16 @@
             }
         }
 
+        void changeVisibility(boolean visible) {
+            if (this.visible == visible) {
+                return;
+            }
+            this.visible = visible;
+            mAfm.notifyViewVisibilityChanged(VirtualContainerView.this, text.id, visible);
+            Log.d(TAG, "visibility changed view: " + text.id + "; visible:" + visible);
+            invalidate();
+        }
+
         Rect getAbsCoordinates() {
             // Must offset the boundaries so they're relative to the CustomView.
             final int offset[] = new int[2];
@@ -290,13 +304,25 @@
             return absBounds;
         }
 
+        void setText(String value) {
+            text.text = value;
+            final AutofillManager autofillManager =
+                    getContext().getSystemService(AutofillManager.class);
+            if (autofillManager != null) {
+                autofillManager.notifyValueChanged(VirtualContainerView.this, text.id,
+                        AutofillValue.forText(text.text));
+            }
+            invalidate();
+        }
+
         void setTextChangedListener(TextWatcher listener) {
             text.listener = listener;
         }
 
         @Override
         public String toString() {
-            return "Label: " + label + " Text: " + text + " Focused: " + focused;
+            return "Label: " + label + " Text: " + text + " Focused: " + focused
+                    + " Visible: " + visible;
         }
 
         final class OneTimeLineWatcher implements TextWatcher {