• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 
17 package com.android.launcher3.tapl;
18 
19 import static com.android.launcher3.tapl.LauncherInstrumentation.WAIT_TIME_MS;
20 import static com.android.launcher3.tapl.LauncherInstrumentation.log;
21 
22 import android.graphics.Rect;
23 
24 import androidx.test.uiautomator.By;
25 import androidx.test.uiautomator.BySelector;
26 import androidx.test.uiautomator.Direction;
27 import androidx.test.uiautomator.UiObject2;
28 import androidx.test.uiautomator.Until;
29 
30 import com.android.launcher3.testing.TestProtocol;
31 
32 import java.util.Collection;
33 
34 /**
35  * All widgets container.
36  */
37 public final class Widgets extends LauncherInstrumentation.VisibleContainer {
38     private static final int FLING_STEPS = 10;
39     private static final int SCROLL_ATTEMPTS = 60;
40 
Widgets(LauncherInstrumentation launcher)41     Widgets(LauncherInstrumentation launcher) {
42         super(launcher);
43         verifyActiveContainer();
44     }
45 
46     /**
47      * Flings forward (down) and waits the fling's end.
48      */
flingForward()49     public void flingForward() {
50         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
51              LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
52                      "want to fling forward in widgets")) {
53             log("Widgets.flingForward enter");
54             final UiObject2 widgetsContainer = verifyActiveContainer();
55             mLauncher.scroll(
56                     widgetsContainer,
57                     Direction.DOWN,
58                     new Rect(0, 0, 0,
59                             mLauncher.getBottomGestureMarginInContainer(widgetsContainer) + 1),
60                     FLING_STEPS, false);
61             try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("flung forward")) {
62                 verifyActiveContainer();
63             }
64             log("Widgets.flingForward exit");
65         }
66     }
67 
68     /**
69      * Flings backward (up) and waits the fling's end.
70      */
flingBackward()71     public void flingBackward() {
72         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
73              LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
74                      "want to fling backwards in widgets")) {
75             log("Widgets.flingBackward enter");
76             final UiObject2 widgetsContainer = verifyActiveContainer();
77             mLauncher.scroll(
78                     widgetsContainer,
79                     Direction.UP,
80                     new Rect(0, 0, mLauncher.getVisibleBounds(widgetsContainer).width(), 0),
81                     FLING_STEPS, false);
82             try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("flung back")) {
83                 verifyActiveContainer();
84             }
85             log("Widgets.flingBackward exit");
86         }
87     }
88 
89     @Override
getContainerType()90     protected LauncherInstrumentation.ContainerType getContainerType() {
91         return LauncherInstrumentation.ContainerType.WIDGETS;
92     }
93 
getWidgetsScroll()94     private int getWidgetsScroll() {
95         return mLauncher.getTestInfo(
96                 TestProtocol.REQUEST_WIDGETS_SCROLL_Y)
97                 .getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
98     }
99 
getWidget(String labelText)100     public Widget getWidget(String labelText) {
101         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
102              LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
103                      "getting widget " + labelText + " in widgets list")) {
104             final UiObject2 searchBar = findSearchBar();
105             final int searchBarHeight = searchBar.getVisibleBounds().height();
106             final UiObject2 fullWidgetsPicker = verifyActiveContainer();
107             mLauncher.assertTrue("Widgets container didn't become scrollable",
108                     fullWidgetsPicker.wait(Until.scrollable(true), WAIT_TIME_MS));
109 
110             final UiObject2 widgetsContainer = findTestAppWidgetsTableContainer();
111             mLauncher.assertTrue("Can't locate widgets list for the test app: "
112                             + mLauncher.getLauncherPackageName(),
113                     widgetsContainer != null);
114             final BySelector labelSelector = By.clazz("android.widget.TextView").text(labelText);
115             final BySelector previewSelector = By.res(mLauncher.getLauncherPackageName(),
116                     "widget_preview");
117             int i = 0;
118             for (; ; ) {
119                 final Collection<UiObject2> tableRows = widgetsContainer.getChildren();
120                 for (UiObject2 row : tableRows) {
121                     final Collection<UiObject2> widgetCells = row.getChildren();
122                     for (UiObject2 widget : widgetCells) {
123                         final UiObject2 label = mLauncher.findObjectInContainer(widget,
124                                 labelSelector);
125                         if (label == null) {
126                             continue;
127                         }
128                         mLauncher.assertEquals(
129                                 "View is not WidgetCell",
130                                 "com.android.launcher3.widget.WidgetCell",
131                                 widget.getClassName());
132                         UiObject2 preview = mLauncher.waitForObjectInContainer(widget,
133                                 previewSelector);
134                         return new Widget(mLauncher, preview);
135                     }
136                 }
137 
138                 mLauncher.assertTrue("Too many attempts", ++i <= SCROLL_ATTEMPTS);
139                 final int scroll = getWidgetsScroll();
140                 mLauncher.scrollDownByDistance(fullWidgetsPicker, searchBarHeight);
141                 final int newScroll = getWidgetsScroll();
142                 mLauncher.assertTrue(
143                         "Scrolled in a wrong direction in Widgets: from " + scroll + " to "
144                                 + newScroll, newScroll >= scroll);
145                 mLauncher.assertTrue("Unable to scroll to the widget", newScroll != scroll);
146             }
147         }
148     }
149 
findSearchBar()150     private UiObject2 findSearchBar() {
151         final BySelector searchBarContainerSelector = By.res(mLauncher.getLauncherPackageName(),
152                 "search_and_recommendations_container");
153         final BySelector searchBarSelector = By.res(mLauncher.getLauncherPackageName(),
154                 "widgets_search_bar");
155         final UiObject2 searchBarContainer = mLauncher.waitForLauncherObject(
156                 searchBarContainerSelector);
157         UiObject2 searchBar = mLauncher.waitForObjectInContainer(searchBarContainer,
158                 searchBarSelector);
159         return searchBar;
160     }
161 
162     /** Finds the widgets list of this test app from the collapsed full widgets picker. */
findTestAppWidgetsTableContainer()163     private UiObject2 findTestAppWidgetsTableContainer() {
164         final BySelector headerSelector = By.res(mLauncher.getLauncherPackageName(),
165                 "widgets_list_header");
166         final BySelector targetAppSelector = By.clazz("android.widget.TextView").text(
167                 mLauncher.getContext().getPackageName());
168         final BySelector widgetsContainerSelector = By.res(mLauncher.getLauncherPackageName(),
169                 "widgets_table");
170 
171         boolean hasHeaderExpanded = false;
172         int scrollDistance = 0;
173         for (int i = 0; i < SCROLL_ATTEMPTS; i++) {
174             UiObject2 fullWidgetsPicker = verifyActiveContainer();
175 
176             UiObject2 header = mLauncher.waitForObjectInContainer(fullWidgetsPicker,
177                     headerSelector);
178             // If a header is barely visible in the bottom edge of the screen, its height could be
179             // too small for a scroll gesture. Since all header should have roughly the same height,
180             // let's pick the max height we have seen so far.
181             scrollDistance = Math.max(scrollDistance, header.getVisibleBounds().height());
182 
183             // Look for a header that has the test app name.
184             UiObject2 headerTitle = mLauncher.findObjectInContainer(fullWidgetsPicker,
185                     targetAppSelector);
186             if (headerTitle != null) {
187                 // If we find the header and it has not been expanded, let's click it to see the
188                 // widgets list. Note that we wait until the header is out of the gesture region at
189                 // the bottom of the screen, because tapping there in Launcher3 causes NexusLauncher
190                 // to briefly appear to handle the gesture, which can break our test.
191                 boolean isHeaderOutOfGestureRegion = headerTitle.getVisibleCenter().y
192                         < mLauncher.getBottomGestureStartOnScreen();
193                 if (!hasHeaderExpanded && isHeaderOutOfGestureRegion) {
194                     log("Header has not been expanded. Click to expand.");
195                     hasHeaderExpanded = true;
196                     mLauncher.clickLauncherObject(headerTitle);
197                 }
198 
199                 // Look for a widgets list.
200                 UiObject2 widgetsContainer = mLauncher.findObjectInContainer(fullWidgetsPicker,
201                         widgetsContainerSelector);
202                 if (widgetsContainer != null) {
203                     log("Widgets container found.");
204                     return widgetsContainer;
205                 }
206             }
207             log("Finding test widget package - scroll with distance: " + scrollDistance);
208             mLauncher.scrollDownByDistance(fullWidgetsPicker, scrollDistance);
209         }
210 
211         return null;
212     }
213 }
214