• 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.shared.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.getRightGestureMarginInContainer(widgetsContainer) + 1,
81                             0),
82                     FLING_STEPS, false);
83             try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("flung back")) {
84                 verifyActiveContainer();
85             }
86             log("Widgets.flingBackward exit");
87         }
88     }
89 
90     @Override
getContainerType()91     protected LauncherInstrumentation.ContainerType getContainerType() {
92         return LauncherInstrumentation.ContainerType.WIDGETS;
93     }
94 
getWidgetsScroll()95     private int getWidgetsScroll() {
96         return mLauncher.getTestInfo(
97                 TestProtocol.REQUEST_WIDGETS_SCROLL_Y)
98                 .getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
99     }
100 
getWidget(String labelText)101     public Widget getWidget(String labelText) {
102         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
103              LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
104                      "getting widget " + labelText + " in widgets list")) {
105             final UiObject2 searchBar = findSearchBar();
106             final int searchBarHeight = searchBar.getVisibleBounds().height();
107             final UiObject2 fullWidgetsPicker = verifyActiveContainer();
108             mLauncher.assertTrue("Widgets container didn't become scrollable",
109                     fullWidgetsPicker.wait(Until.scrollable(true), WAIT_TIME_MS));
110 
111             final UiObject2 widgetsContainer = findTestAppWidgetsTableContainer();
112             mLauncher.assertTrue("Can't locate widgets list for the test app: "
113                             + mLauncher.getLauncherPackageName(),
114                     widgetsContainer != null);
115             final BySelector labelSelector = By.clazz("android.widget.TextView").text(labelText);
116             final BySelector previewSelector = By.res(mLauncher.getLauncherPackageName(),
117                     "widget_preview");
118             final int bottomGestureStartOnScreen = mLauncher.getBottomGestureStartOnScreen();
119             int i = 0;
120             for (; ; ) {
121                 final Collection<UiObject2> tableRows = mLauncher.getChildren(widgetsContainer);
122                 for (UiObject2 row : tableRows) {
123                     final Collection<UiObject2> widgetCells = mLauncher.getChildren(row);
124                     for (UiObject2 widget : widgetCells) {
125                         final UiObject2 label = mLauncher.findObjectInContainer(widget,
126                                 labelSelector);
127                         if (label == null) {
128                             continue;
129                         }
130                         if (widget.getVisibleCenter().y >= bottomGestureStartOnScreen) {
131                             continue;
132                         }
133                         mLauncher.assertEquals(
134                                 "View is not WidgetCell",
135                                 "com.android.launcher3.widget.WidgetCell",
136                                 widget.getClassName());
137                         UiObject2 preview = mLauncher.waitForObjectInContainer(widget,
138                                 previewSelector);
139                         return new Widget(mLauncher, preview);
140                     }
141                 }
142 
143                 mLauncher.assertTrue("Too many attempts", ++i <= SCROLL_ATTEMPTS);
144                 final int scroll = getWidgetsScroll();
145                 mLauncher.scrollDownByDistance(fullWidgetsPicker, searchBarHeight);
146                 final int newScroll = getWidgetsScroll();
147                 mLauncher.assertTrue(
148                         "Scrolled in a wrong direction in Widgets: from " + scroll + " to "
149                                 + newScroll, newScroll >= scroll);
150                 mLauncher.assertTrue("Unable to scroll to the widget", newScroll != scroll);
151             }
152         }
153     }
154 
findSearchBar()155     private UiObject2 findSearchBar() {
156         final BySelector searchBarContainerSelector = By.res(mLauncher.getLauncherPackageName(),
157                 "search_and_recommendations_container");
158         final BySelector searchBarSelector = By.res(mLauncher.getLauncherPackageName(),
159                 "widgets_search_bar");
160         final UiObject2 searchBarContainer = mLauncher.waitForLauncherObject(
161                 searchBarContainerSelector);
162         UiObject2 searchBar = mLauncher.waitForObjectInContainer(searchBarContainer,
163                 searchBarSelector);
164         return searchBar;
165     }
166 
167     /** Finds the widgets list of this test app from the collapsed full widgets picker. */
findTestAppWidgetsTableContainer()168     private UiObject2 findTestAppWidgetsTableContainer() {
169         final BySelector headerSelector = By.res(mLauncher.getLauncherPackageName(),
170                 "widgets_list_header");
171         final BySelector targetAppSelector = By.clazz("android.widget.TextView").text(
172                 mLauncher.getContext().getPackageName());
173         final BySelector widgetsContainerSelector = By.res(mLauncher.getLauncherPackageName(),
174                 "widgets_table");
175 
176         boolean hasHeaderExpanded = false;
177         int scrollDistance = 0;
178         for (int i = 0; i < SCROLL_ATTEMPTS; i++) {
179             UiObject2 fullWidgetsPicker = verifyActiveContainer();
180 
181             UiObject2 header = mLauncher.waitForObjectInContainer(fullWidgetsPicker,
182                     headerSelector);
183             // If a header is barely visible in the bottom edge of the screen, its height could be
184             // too small for a scroll gesture. Since all header should have roughly the same height,
185             // let's pick the max height we have seen so far.
186             scrollDistance = Math.max(scrollDistance, header.getVisibleBounds().height());
187 
188             // Look for a header that has the test app name.
189             UiObject2 headerTitle = mLauncher.findObjectInContainer(fullWidgetsPicker,
190                     targetAppSelector);
191             if (headerTitle != null) {
192                 // If we find the header and it has not been expanded, let's click it to see the
193                 // widgets list. Note that we wait until the header is out of the gesture region at
194                 // the bottom of the screen, because tapping there in Launcher3 causes NexusLauncher
195                 // to briefly appear to handle the gesture, which can break our test.
196                 boolean isHeaderOutOfGestureRegion = headerTitle.getVisibleCenter().y
197                         < mLauncher.getBottomGestureStartOnScreen();
198                 if (!hasHeaderExpanded && isHeaderOutOfGestureRegion) {
199                     log("Header has not been expanded. Click to expand.");
200                     hasHeaderExpanded = true;
201                     mLauncher.clickLauncherObject(headerTitle);
202                 }
203 
204                 // Look for a widgets list.
205                 UiObject2 widgetsContainer = mLauncher.findObjectInContainer(fullWidgetsPicker,
206                         widgetsContainerSelector);
207                 if (widgetsContainer != null) {
208                     log("Widgets container found.");
209                     return widgetsContainer;
210                 }
211             }
212             log("Finding test widget package - scroll with distance: " + scrollDistance);
213             mLauncher.scrollDownByDistance(fullWidgetsPicker, scrollDistance);
214         }
215 
216         return null;
217     }
218 }
219