summaryrefslogtreecommitdiff
path: root/tests/autofillservice/src/android/autofillservice/cts/DuplicateIdActivityTest.java
blob: 29ec2b166d4cc9229356b317cbc0ba575d2d69dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.autofillservice.cts;

import static android.autofillservice.cts.CannedFillResponse.NO_RESPONSE;
import static android.autofillservice.cts.DuplicateIdActivity.DUPLICATE_ID;
import static android.autofillservice.cts.common.ShellHelper.runShellCommand;

import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assume.assumeTrue;

import android.app.assist.AssistStructure;
import android.util.Log;
import android.view.autofill.AutofillId;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

public class DuplicateIdActivityTest extends AutoFillServiceTestCase {
    private static final String LOG_TAG = DuplicateIdActivityTest.class.getSimpleName();
    @Rule
    public final AutofillActivityTestRule<DuplicateIdActivity> mActivityRule = new AutofillActivityTestRule<>(
            DuplicateIdActivity.class);

    private DuplicateIdActivity mActivity;

    @Before
    public void setup() throws Exception {
        Helper.disableAutoRotation(mUiBot);
        mUiBot.setScreenOrientation(0);

        mActivity = mActivityRule.getActivity();
    }

    @After
    public void teardown() {
        mActivity.finish();

        Helper.allowAutoRotation();
    }

    /**
     * Find the views that are tested from the structure in the request
     *
     * @param request The request
     *
     * @return An array containing the two tested views
     */
    private AssistStructure.ViewNode[] findViews(InstrumentedAutoFillService.FillRequest request) {
        assertThat(request.structure.getWindowNodeCount()).isEqualTo(1);
        AssistStructure.WindowNode windowNode = request.structure.getWindowNodeAt(0);

        AssistStructure.ViewNode rootNode = windowNode.getRootViewNode();

        assertThat(rootNode.getChildCount()).isEqualTo(2);
        return new AssistStructure.ViewNode[]{rootNode.getChildAt(0), rootNode.getChildAt(1)};
    }

    @Test
    public void testDoNotRestoreDuplicateAutofillIds() throws Exception {
        assumeTrue("Rotation is supported", Helper.isRotationSupported(mContext));

        enableService();

        sReplier.addResponse(new CannedFillResponse.Builder()
                .addDataset(new CannedFillResponse.CannedDataset.Builder()
                        .setField(DUPLICATE_ID, "value")
                        .setPresentation(createPresentation("dataset"))
                        .build())
                .build());

        // Select field to start autofill
        runShellCommand("input keyevent KEYCODE_TAB");

        InstrumentedAutoFillService.FillRequest request = sReplier.getNextFillRequest();

        AssistStructure.ViewNode[] views = findViews(request);
        AssistStructure.ViewNode view1 = views[0];
        AssistStructure.ViewNode view2 = views[1];
        AutofillId id1 = view1.getAutofillId();
        AutofillId id2 = view2.getAutofillId();

        Log.i(LOG_TAG, "view1=" + id1);
        Log.i(LOG_TAG, "view2=" + id2);

        // Both checkboxes use the same id
        assertThat(view1.getId()).isEqualTo(view2.getId());

        // They got different autofill ids though
        assertThat(id1).isNotEqualTo(id2);

        sReplier.addResponse(NO_RESPONSE);

        // Force rotation to force onDestroy->onCreate cycle
        mUiBot.setScreenOrientation(1);
        // Wait context and Views being recreated in rotation
        mUiBot.assertShownByRelativeId(DUPLICATE_ID);

        // Because service returned a null response, rotation will trigger another request.
        sReplier.addResponse(NO_RESPONSE);

        // Select other field to trigger new partition
        runShellCommand("input keyevent KEYCODE_TAB");

        request = sReplier.getNextFillRequest();

        // Ignore 2nd request.
        sReplier.getNextFillRequest();

        views = findViews(request);
        AutofillId recreatedId1 = views[0].getAutofillId();
        AutofillId recreatedId2 = views[1].getAutofillId();

        Log.i(LOG_TAG, "restored view1=" + recreatedId1);
        Log.i(LOG_TAG, "restored view2=" + recreatedId2);

        // For the restoring logic the two views are the same. Hence it might happen that the first
        // view is restored with the id of the second view or the other way round.
        // We just need
        // - to restore as many views as we can (i.e. one)
        // - make sure the autofill ids are still unique after
        boolean view1WasRestored = (recreatedId1.equals(id1) || recreatedId1.equals(id2));
        boolean view2WasRestored = (recreatedId2.equals(id1) || recreatedId2.equals(id2));

        // One id was restored
        assertThat(view1WasRestored || view2WasRestored).isTrue();

        // The views still have different autofill ids
        assertThat(recreatedId1).isNotEqualTo(recreatedId2);
    }
}