1 /*
2  * Copyright (C) 2022 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 androidx.annotation.NonNull;
20 import androidx.test.uiautomator.By;
21 import androidx.test.uiautomator.BySelector;
22 import androidx.test.uiautomator.UiObject2;
23 import androidx.test.uiautomator.Until;
24 
25 import java.util.regex.Pattern;
26 
27 /**
28  * Operations on qsb from either Home screen or AllApp screen.
29  */
30 public abstract class Qsb implements SearchInputSource {
31 
32     private static final String ASSISTANT_APP_PACKAGE = "com.google.android.googlequicksearchbox";
33     private static final String ASSISTANT_ICON_RES_ID = "mic_icon";
34     private static final String LENS_ICON_RES_ID = "lens_icon";
35     private static final Pattern LENS_APP_RES_PATTERN = Pattern.compile(
36             ASSISTANT_APP_PACKAGE + ":id/lens.*");
37     protected final LauncherInstrumentation mLauncher;
38     private final UiObject2 mContainer;
39     private final String mQsbResName;
40 
Qsb(LauncherInstrumentation launcher, UiObject2 container, String qsbResName)41     protected Qsb(LauncherInstrumentation launcher, UiObject2 container, String qsbResName) {
42         mLauncher = launcher;
43         mContainer = container;
44         mQsbResName = qsbResName;
45         waitForQsbObject();
46     }
47 
48     // Waits for the quick search box.
waitForQsbObject()49     private UiObject2 waitForQsbObject() {
50         return mLauncher.waitForObjectInContainer(mContainer, mQsbResName);
51     }
52 
53     /**
54      * Launch assistant app by tapping mic icon on qsb.
55      */
56 
57     @NonNull
launchAssistant()58     public LaunchedAppState launchAssistant() {
59         try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
60                 "want to click assistant mic icon button");
61              LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
62             UiObject2 assistantIcon = mLauncher.waitForLauncherObject(ASSISTANT_ICON_RES_ID);
63 
64             LauncherInstrumentation.log("Qsb.launchAssistant before click "
65                     + assistantIcon.getVisibleCenter() + " in "
66                     + mLauncher.getVisibleBounds(assistantIcon));
67 
68             mLauncher.clickLauncherObject(assistantIcon);
69 
70             try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("clicked")) {
71                 // assert Assistant App Launched
72                 BySelector selector = By.pkg(ASSISTANT_APP_PACKAGE);
73                 mLauncher.assertTrue(
74                         "assistant app didn't start: (" + selector + ")",
75                         mLauncher.getDevice().wait(Until.hasObject(selector),
76                                 LauncherInstrumentation.WAIT_TIME_MS)
77                 );
78                 return new LaunchedAppState(mLauncher);
79             }
80         }
81     }
82 
83     /**
84      * Launches lens app by tapping lens icon on qsb.
85      */
86     @NonNull
launchLens()87     public LaunchedAppState launchLens() {
88         try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
89                 "want to click lens icon button");
90              LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
91             UiObject2 lensIcon = mLauncher.waitForLauncherObject(LENS_ICON_RES_ID);
92 
93             LauncherInstrumentation.log("Qsb.launchLens before click "
94                     + lensIcon.getVisibleCenter() + " in "
95                     + mLauncher.getVisibleBounds(lensIcon));
96 
97             mLauncher.clickLauncherObject(lensIcon);
98 
99             try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("clicked")) {
100                 // Package name is not enough to check if the app is launched, because many
101                 // elements are having googlequicksearchbox as package name. So it checks if the
102                 // corresponding app resource is displayed
103                 BySelector selector = By.res(LENS_APP_RES_PATTERN);
104                 mLauncher.assertTrue(
105                         "Lens app didn't start: (" + selector + ")",
106                         mLauncher.getDevice().wait(Until.hasObject(selector),
107                                 LauncherInstrumentation.WAIT_TIME_MS)
108                 );
109                 return new LaunchedAppState(mLauncher);
110             }
111         }
112     }
113 
114     /**
115      * Show search result page from tapping qsb.
116      */
showSearchResult()117     public SearchResultFromQsb showSearchResult() {
118         try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
119                 "want to open search result page");
120              LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
121             clickQsb();
122             try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer(
123                     "clicked qsb to open search result page")) {
124                 return createSearchResult();
125             }
126         }
127     }
128 
clickQsb()129     protected void clickQsb() {
130         mLauncher.clickLauncherObject(waitForQsbObject());
131     }
132 
133     @Override
getLauncher()134     public LauncherInstrumentation getLauncher() {
135         return mLauncher;
136     }
137 
138     @Override
getSearchResultForInput()139     public SearchResultFromQsb getSearchResultForInput() {
140         return createSearchResult();
141     }
142 
createSearchResult()143     protected SearchResultFromQsb createSearchResult() {
144         return new SearchResultFromQsb(mLauncher);
145     }
146 }
147