xref: /aosp_15_r20/cts/tests/autofillservice/src/android/autofillservice/cts/activities/GridActivity.java (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package android.autofillservice.cts.activities;
17 
18 import android.autofillservice.cts.R;
19 import android.autofillservice.cts.testcore.Helper;
20 import android.autofillservice.cts.testcore.OneTimeTextWatcher;
21 import android.autofillservice.cts.testcore.Visitor;
22 import android.os.Bundle;
23 import android.util.Log;
24 import android.view.autofill.AutofillManager;
25 import android.widget.Button;
26 import android.widget.EditText;
27 import android.widget.GridLayout;
28 
29 import com.android.compatibility.common.util.RetryableException;
30 
31 import java.util.ArrayList;
32 import java.util.concurrent.BlockingQueue;
33 import java.util.concurrent.LinkedBlockingQueue;
34 import java.util.concurrent.TimeUnit;
35 
36 /**
37  * Activity that contains a 4x4 grid of cells (named {@code l1c1} to {@code l4c2}) plus
38  * {@code save} and {@code clear} buttons.
39  */
40 public class GridActivity extends AbstractAutoFillActivity {
41 
42     private static final String TAG = "GridActivity";
43     private static final int N_ROWS = 4;
44     private static final int N_COLS = 2;
45 
46     public static final String ID_L1C1 = getResourceId(1, 1);
47     public static final String ID_L1C2 = getResourceId(1, 2);
48     public static final String ID_L2C1 = getResourceId(2, 1);
49     public static final String ID_L2C2 = getResourceId(2, 2);
50     public static final String ID_L3C1 = getResourceId(3, 1);
51     public static final String ID_L3C2 = getResourceId(3, 2);
52     public static final String ID_L4C1 = getResourceId(4, 1);
53     public static final String ID_L4C2 = getResourceId(4, 2);
54 
55     private GridLayout mGrid;
56     private final EditText[][] mCells = new EditText[4][2];
57     private Button mSaveButton;
58     private Button mClearButton;
59 
60     @Override
onCreate(Bundle savedInstanceState)61     protected void onCreate(Bundle savedInstanceState) {
62         super.onCreate(savedInstanceState);
63 
64         setContentView(R.layout.grid_activity);
65 
66         mGrid = findViewById(R.id.grid);
67         mCells[0][0] = findViewById(R.id.l1c1);
68         mCells[0][1] = findViewById(R.id.l1c2);
69         mCells[1][0] = findViewById(R.id.l2c1);
70         mCells[1][1] = findViewById(R.id.l2c2);
71         mCells[2][0] = findViewById(R.id.l3c1);
72         mCells[2][1] = findViewById(R.id.l3c2);
73         mCells[3][0] = findViewById(R.id.l4c1);
74         mCells[3][1] = findViewById(R.id.l4c2);
75         mSaveButton = findViewById(R.id.save);
76         mClearButton = findViewById(R.id.clear);
77 
78         mSaveButton.setOnClickListener((v) -> save());
79         mClearButton.setOnClickListener((v) -> resetFields());
80     }
81 
save()82     public void save() {
83         getSystemService(AutofillManager.class).commit();
84     }
85 
resetFields()86     public void resetFields() {
87         for (int i = 0; i < N_ROWS; i++) {
88             for (int j = 0; j < N_COLS; j++) {
89                 mCells[i][j].setText("");
90             }
91         }
92         getSystemService(AutofillManager.class).cancel();
93     }
94 
getCell(int row, int column)95     public EditText getCell(int row, int column) {
96         return mCells[row - 1][column - 1];
97     }
98 
getResourceId(int line, int col)99     public static String getResourceId(int line, int col) {
100         return "l" + line + "c" + col;
101     }
102 
onCell(int row, int column, Visitor<EditText> v)103     public void onCell(int row, int column, Visitor<EditText> v) {
104         final EditText cell = getCell(row, column);
105         syncRunOnUiThread(() -> v.visit(cell));
106     }
107 
focusCell(int row, int column)108     public void focusCell(int row, int column) {
109         onCell(row, column, EditText::requestFocus);
110     }
111 
clearCell(int row, int column)112     public void clearCell(int row, int column) {
113         onCell(row, column, (c) -> c.setText(""));
114     }
115 
setText(int row, int column, String text)116     public void setText(int row, int column, String text) {
117         onCell(row, column, (c) -> c.setText(text));
118     }
119 
forceAutofill(int row, int column)120     public void forceAutofill(int row, int column) {
121         onCell(row, column, (c) -> getAutofillManager().requestAutofill(c));
122     }
123 
removeCell(int row, int column)124     public void removeCell(int row, int column) {
125         onCell(row, column, (c) -> mGrid.removeView(c));
126     }
127 
addCell(int row, int column, EditText cell)128     public void addCell(int row, int column, EditText cell) {
129         mCells[row - 1][column - 1] = cell;
130         // TODO: ideally it should be added in the right place...
131         syncRunOnUiThread(() -> mGrid.addView(cell));
132     }
133 
triggerAutofill(boolean manually, int row, int column)134     public void triggerAutofill(boolean manually, int row, int column) {
135         if (manually) {
136             forceAutofill(row, column);
137         } else {
138             focusCell(row, column);
139         }
140     }
141 
getText(int row, int column)142     public String getText(int row, int column) throws InterruptedException {
143         final long timeoutMs = 100;
144         final BlockingQueue<String> queue = new LinkedBlockingQueue<>(1);
145         onCell(row, column, (c) -> Helper.offer(queue, c.getText().toString(), timeoutMs));
146         final String text = queue.poll(timeoutMs, TimeUnit.MILLISECONDS);
147         if (text == null) {
148             throw new RetryableException("text not set in " + timeoutMs + "ms");
149         }
150         return text;
151     }
152 
expectAutofill()153     public FillExpectation expectAutofill() {
154         return new FillExpectation();
155     }
156 
dumpCells()157     public void dumpCells() {
158         final StringBuilder output = new StringBuilder("dumpCells():\n");
159         for (int i = 0; i < N_ROWS; i++) {
160             for (int j = 0; j < N_COLS; j++) {
161                 final String id = getResourceId(i + 1, j + 1);
162                 final String value = mCells[i][j].getText().toString();
163                 output.append('\t').append(id).append("='").append(value).append("'\n");
164             }
165         }
166         Log.d(TAG, output.toString());
167     }
168 
169     public final class FillExpectation {
170 
171         private final ArrayList<OneTimeTextWatcher> mWatchers = new ArrayList<>();
172 
onCell(int line, int col, String value)173         public FillExpectation onCell(int line, int col, String value) {
174             final String resourceId = getResourceId(line, col);
175             final EditText cell = getCell(line, col);
176             final OneTimeTextWatcher watcher = new OneTimeTextWatcher(resourceId, cell, value);
177             mWatchers.add(watcher);
178             cell.addTextChangedListener(watcher);
179             return this;
180         }
181 
assertAutoFilled()182         public void assertAutoFilled() throws Exception {
183             try {
184                 for (int i = 0; i < mWatchers.size(); i++) {
185                     final OneTimeTextWatcher watcher = mWatchers.get(i);
186                     watcher.assertAutoFilled();
187                 }
188             } catch (AssertionError | Exception e) {
189                 dumpCells();
190                 throw e;
191             }
192         }
193     }
194 }
195