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 
20 import android.graphics.Point;
21 import android.widget.TextView;
22 
23 import androidx.annotation.NonNull;
24 import androidx.test.uiautomator.By;
25 import androidx.test.uiautomator.BySelector;
26 import androidx.test.uiautomator.UiObject2;
27 
28 import com.android.launcher3.testing.shared.TestProtocol;
29 
30 import java.util.regex.Pattern;
31 
32 /**
33  * App icon, whether in all apps, workspace or the taskbar.
34  */
35 public abstract class AppIcon extends Launchable {
36 
AppIcon(LauncherInstrumentation launcher, UiObject2 icon)37     AppIcon(LauncherInstrumentation launcher, UiObject2 icon) {
38         super(launcher, icon);
39     }
40 
41     /**
42      * Find an app icon with the given name.
43      *
44      * @param appName app icon to look for
45      */
getAppIconSelector(String appName)46     static BySelector getAppIconSelector(String appName) {
47         // focusable=true to avoid matching folder labels
48         return By.clazz(TextView.class).text(makeMultilinePattern(appName)).focusable(true);
49     }
50 
51     /**
52      * Find an app icon with the given name.
53      *
54      * @param appName  app icon to look for
55      * @param launcher (optional) - only match ui elements from Launcher's package
56      */
getAppIconSelector(String appName, LauncherInstrumentation launcher)57     static BySelector getAppIconSelector(String appName, LauncherInstrumentation launcher) {
58         return getAppIconSelector(appName).pkg(launcher.getLauncherPackageName());
59     }
60 
getMenuItemSelector(String text, LauncherInstrumentation launcher)61     static BySelector getMenuItemSelector(String text, LauncherInstrumentation launcher) {
62         return By.clazz(TextView.class).text(text).pkg(launcher.getLauncherPackageName());
63     }
64 
getAnyAppIconSelector()65     static BySelector getAnyAppIconSelector() {
66         return By.clazz(TextView.class);
67     }
68 
getLongClickEvent()69     protected abstract Pattern getLongClickEvent();
70 
71     /**
72      * Long-clicks the icon to open its menu.
73      */
openMenu()74     public AppIconMenu openMenu() {
75         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
76             return createMenu(mLauncher.clickAndGet(
77                     mObject, /* resName= */ "popup_container", getLongClickEvent()));
78         }
79     }
80 
81     /**
82      * Long-clicks the icon to open its menu, and looks at the deep shortcuts container only.
83      */
openDeepShortcutMenu()84     public AppIconMenu openDeepShortcutMenu() {
85         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
86             return createMenu(mLauncher.clickAndGet(
87                     mObject, /* resName= */ "deep_shortcuts_container", getLongClickEvent()));
88         }
89     }
90 
createMenu(UiObject2 menu)91     protected abstract AppIconMenu createMenu(UiObject2 menu);
92 
93     @Override
addExpectedEventsForLongClick()94     protected void addExpectedEventsForLongClick() {
95         mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, getLongClickEvent());
96     }
97 
98     @Override
waitForLongPressConfirmation()99     protected void waitForLongPressConfirmation() {
100         mLauncher.waitForLauncherObject("popup_container");
101     }
102 
103     @Override
expectActivityStartEvents()104     protected void expectActivityStartEvents() {
105         mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_START);
106     }
107 
108     @Override
launchableType()109     protected String launchableType() {
110         return "app icon";
111     }
112 
113     /** Return the app name of a icon */
114     @NonNull
getIconName()115     public String getIconName() {
116         return getObject().getText();
117     }
118 
119     /**
120      * Return the app name of a icon by the content description. This should be used when trying to
121      * get the name of an app where the text of it is multiline.
122      */
123     @NonNull
getAppName()124     String getAppName() {
125         return getObject().getContentDescription();
126     }
127 
128     /**
129      * @return the center coordinates of the icon
130      */
131     @NonNull
getVisibleCenter()132     public Point getVisibleCenter() {
133         return getObject().getVisibleCenter();
134     }
135 
136     /**
137      * Create a regular expression pattern that matches strings containing all of the non-whitespace
138      * characters of the app name, with any amount of whitespace added between characters (e.g.
139      * newline for multiline app labels).
140      */
makeMultilinePattern(String appName)141     static Pattern makeMultilinePattern(String appName) {
142         // Remove any existing whitespace.
143         appName = appName.replaceAll("\\s", "");
144         // Allow whitespace between characters, e.g. newline for 2 line app label.
145         StringBuilder regexBuldier = new StringBuilder("\\s*");
146         appName.chars().forEach(letter -> regexBuldier.append((char) letter).append("\\s*"));
147         return Pattern.compile(regexBuldier.toString());
148     }
149 }
150