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 package com.android.launcher3.tapl; 17 18 import static android.view.KeyEvent.KEYCODE_META_RIGHT; 19 20 import static com.android.launcher3.tapl.LauncherInstrumentation.TASKBAR_RES_ID; 21 22 import android.graphics.Point; 23 import android.graphics.Rect; 24 import android.os.SystemClock; 25 import android.text.TextUtils; 26 import android.view.MotionEvent; 27 import android.widget.TextView; 28 29 import androidx.annotation.NonNull; 30 import androidx.test.uiautomator.By; 31 import androidx.test.uiautomator.BySelector; 32 import androidx.test.uiautomator.UiObject2; 33 34 import org.junit.Assert; 35 36 import java.util.List; 37 import java.util.stream.Collectors; 38 39 /** 40 * Operations on the Taskbar from LaunchedApp. 41 */ 42 public final class Taskbar { 43 44 private final LauncherInstrumentation mLauncher; 45 Taskbar(LauncherInstrumentation launcher)46 Taskbar(LauncherInstrumentation launcher) { 47 mLauncher = launcher; 48 try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( 49 "expect new taskbar to be visible")) { 50 mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID); 51 } 52 53 if (!mLauncher.isTransientTaskbar()) { 54 Assert.assertEquals("Persistent taskbar should fill screen width", 55 getVisibleBounds().width(), mLauncher.getRealDisplaySize().x); 56 } 57 } 58 59 /** 60 * Returns an app icon with the given name. This fails if the icon is not found. 61 */ 62 @NonNull getAppIcon(String appName)63 public TaskbarAppIcon getAppIcon(String appName) { 64 try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( 65 "want to get a taskbar icon")) { 66 return new TaskbarAppIcon(mLauncher, mLauncher.waitForObjectInContainer( 67 mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID), 68 AppIcon.getAppIconSelector(appName, mLauncher))); 69 } 70 } 71 72 /** 73 * Stashes this taskbar. 74 * <p> 75 * The taskbar must already be unstashed and in transient mode when calling this method. 76 */ swipeDownToStash()77 public void swipeDownToStash() { 78 mLauncher.assertTrue("Taskbar is not transient, swipe down not supported", 79 mLauncher.isTransientTaskbar()); 80 81 try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( 82 "want to hide the taskbar"); 83 LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) { 84 mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID); 85 86 Rect taskbarBounds = getVisibleBounds(); 87 int startX = taskbarBounds.centerX(); 88 int startY = taskbarBounds.centerY(); 89 int endX = startX; 90 int endY = mLauncher.getRealDisplaySize().y - 1; 91 92 mLauncher.linearGesture(startX, startY, endX, endY, 10, false, 93 LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER); 94 LauncherInstrumentation.log("swipeDownToStash: sent linear swipe down gesture"); 95 try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer( 96 "expect transient taskbar to be hidden after swipe down")) { 97 mLauncher.waitUntilSystemLauncherObjectGone(TASKBAR_RES_ID); 98 } 99 } 100 } 101 102 /** 103 * Opens the Taskbar all apps page. 104 */ openAllApps()105 public TaskbarAllApps openAllApps() { 106 try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( 107 "want to open taskbar all apps"); 108 LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) { 109 110 mLauncher.clickLauncherObject(mLauncher.waitForObjectInContainer( 111 mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID), 112 getAllAppsButtonSelector())); 113 114 return getAllApps(); 115 } 116 } 117 118 /** Opens the Taskbar all apps page with the meta keyboard shortcut. */ openAllAppsFromKeyboardShortcut()119 public TaskbarAllApps openAllAppsFromKeyboardShortcut() { 120 try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) { 121 mLauncher.getDevice().pressKeyCode(KEYCODE_META_RIGHT); 122 try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( 123 "pressed meta key")) { 124 return getAllApps(); 125 } 126 } 127 } 128 129 /** Returns {@link TaskbarAllApps} if it is open, otherwise fails. */ getAllApps()130 public TaskbarAllApps getAllApps() { 131 try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( 132 "want to get taskbar all apps object")) { 133 return new TaskbarAllApps(mLauncher); 134 } 135 } 136 137 /** Returns a list of app icon names on the Taskbar */ getIconNames()138 public List<String> getIconNames() { 139 try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( 140 "want to get all taskbar icons")) { 141 return mLauncher.waitForObjectsInContainer( 142 mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID), 143 AppIcon.getAnyAppIconSelector()) 144 .stream() 145 .map(UiObject2::getText) 146 .filter(text -> !TextUtils.isEmpty(text)) // Filter out the all apps button 147 .collect(Collectors.toList()); 148 } 149 } 150 getAllAppsButtonSelector()151 private static BySelector getAllAppsButtonSelector() { 152 // Look for an icon with no text 153 return By.clazz(TextView.class).text(""); 154 } 155 getVisibleBounds()156 public Rect getVisibleBounds() { 157 return mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID).getVisibleBounds(); 158 } 159 160 /** 161 * Touch either on the right or the left corner of the screen, 1 pixel from the bottom and 162 * from the sides. 163 */ touchBottomCorner(boolean tapRight)164 void touchBottomCorner(boolean tapRight) { 165 try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( 166 "want to tap bottom corner on the " + (tapRight ? "right" : "left"))) { 167 final long downTime = SystemClock.uptimeMillis(); 168 final Point tapTarget = new Point( 169 tapRight 170 ? 171 getVisibleBounds().right 172 - mLauncher.getTargetInsets().right 173 - 1 174 : getVisibleBounds().left 175 + 1, 176 mLauncher.getRealDisplaySize().y - 1); 177 178 mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, tapTarget, 179 LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER); 180 mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP, tapTarget, 181 LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER); 182 } 183 } 184 } 185