1 /* 2 * Copyright (C) 2019 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.ui; 18 19 import static androidx.test.InstrumentationRegistry.getInstrumentation; 20 21 import static com.google.common.truth.Truth.assertThat; 22 23 import static org.junit.Assert.assertEquals; 24 import static org.junit.Assert.assertFalse; 25 import static org.junit.Assert.assertNotNull; 26 import static org.junit.Assert.assertNull; 27 import static org.junit.Assert.assertTrue; 28 import static org.junit.Assume.assumeTrue; 29 30 import android.content.Intent; 31 import android.graphics.Point; 32 import android.os.SystemClock; 33 import android.platform.test.annotations.IwTest; 34 import android.util.Log; 35 36 import androidx.test.filters.LargeTest; 37 import androidx.test.runner.AndroidJUnit4; 38 39 import com.android.launcher3.Launcher; 40 import com.android.launcher3.LauncherState; 41 import com.android.launcher3.popup.ArrowPopup; 42 import com.android.launcher3.tapl.AllApps; 43 import com.android.launcher3.tapl.AppIcon; 44 import com.android.launcher3.tapl.AppIconMenu; 45 import com.android.launcher3.tapl.AppIconMenuItem; 46 import com.android.launcher3.tapl.Folder; 47 import com.android.launcher3.tapl.FolderIcon; 48 import com.android.launcher3.tapl.HomeAllApps; 49 import com.android.launcher3.tapl.HomeAppIcon; 50 import com.android.launcher3.tapl.HomeAppIconMenu; 51 import com.android.launcher3.tapl.HomeAppIconMenuItem; 52 import com.android.launcher3.tapl.Widgets; 53 import com.android.launcher3.tapl.Workspace; 54 import com.android.launcher3.util.TestUtil; 55 import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord; 56 import com.android.launcher3.util.rule.TISBindRule; 57 import com.android.launcher3.widget.picker.WidgetsFullSheet; 58 import com.android.launcher3.widget.picker.WidgetsRecyclerView; 59 60 import org.junit.Before; 61 import org.junit.Ignore; 62 import org.junit.Rule; 63 import org.junit.Test; 64 import org.junit.runner.RunWith; 65 66 import java.io.IOException; 67 import java.util.Map; 68 69 @LargeTest 70 @RunWith(AndroidJUnit4.class) 71 public class TaplTestsLauncher3 extends AbstractLauncherUiTest { 72 private static final String APP_NAME = "LauncherTestApp"; 73 private static final String DUMMY_APP_NAME = "Aardwolf"; 74 private static final String MAPS_APP_NAME = "Maps"; 75 private static final String STORE_APP_NAME = "Play Store"; 76 private static final String GMAIL_APP_NAME = "Gmail"; 77 78 @Rule 79 public TISBindRule mTISBindRule = new TISBindRule(); 80 81 @Before setUp()82 public void setUp() throws Exception { 83 super.setUp(); 84 initialize(this); 85 } 86 initialize(AbstractLauncherUiTest test)87 public static void initialize(AbstractLauncherUiTest test) throws Exception { 88 test.clearLauncherData(); 89 test.mDevice.pressHome(); 90 test.waitForLauncherCondition("Launcher didn't start", launcher -> launcher != null); 91 test.waitForState("Launcher internal state didn't switch to Home", 92 () -> LauncherState.NORMAL); 93 test.waitForResumed("Launcher internal state is still Background"); 94 // Check that we switched to home. 95 test.mLauncher.getWorkspace(); 96 AbstractLauncherUiTest.checkDetectedLeaks(test.mLauncher); 97 } 98 99 // Please don't add negative test cases for methods that fail only after a long wait. expectFail(String message, Runnable action)100 public static void expectFail(String message, Runnable action) { 101 boolean failed = false; 102 try { 103 action.run(); 104 } catch (AssertionError e) { 105 failed = true; 106 } 107 assertTrue(message, failed); 108 } 109 isWorkspaceScrollable(Launcher launcher)110 public static boolean isWorkspaceScrollable(Launcher launcher) { 111 return launcher.getWorkspace().getPageCount() > launcher.getWorkspace().getPanelCount(); 112 } 113 getCurrentWorkspacePage(Launcher launcher)114 private int getCurrentWorkspacePage(Launcher launcher) { 115 return launcher.getWorkspace().getCurrentPage(); 116 } 117 getWidgetsView(Launcher launcher)118 private WidgetsRecyclerView getWidgetsView(Launcher launcher) { 119 return WidgetsFullSheet.getWidgetsView(launcher); 120 } 121 122 @Test testDevicePressMenu()123 public void testDevicePressMenu() throws Exception { 124 mDevice.pressMenu(); 125 mDevice.waitForIdle(); 126 executeOnLauncher( 127 launcher -> assertNotNull("Launcher internal state didn't switch to Showing Menu", 128 launcher.getOptionsPopup())); 129 // Check that pressHome works when the menu is shown. 130 mLauncher.goHome(); 131 } 132 133 @Test 134 @ScreenRecord testPressHomeOnAllAppsContextMenu()135 public void testPressHomeOnAllAppsContextMenu() throws Exception { 136 final AllApps allApps = mLauncher.getWorkspace().switchToAllApps(); 137 allApps.freeze(); 138 try { 139 allApps.getAppIcon("TestActivity7").openMenu(); 140 } finally { 141 allApps.unfreeze(); 142 } 143 mLauncher.goHome(); 144 } 145 runAllAppsTest(AbstractLauncherUiTest test, AllApps allApps)146 public static void runAllAppsTest(AbstractLauncherUiTest test, AllApps allApps) { 147 allApps.freeze(); 148 try { 149 assertNotNull("allApps parameter is null", allApps); 150 151 assertTrue( 152 "Launcher internal state is not All Apps", 153 test.isInState(() -> LauncherState.ALL_APPS)); 154 155 // Test flinging forward and backward. 156 test.executeOnLauncher(launcher -> assertEquals( 157 "All Apps started in already scrolled state", 0, 158 test.getAllAppsScroll(launcher))); 159 160 allApps.flingForward(); 161 assertTrue("Launcher internal state is not All Apps", 162 test.isInState(() -> LauncherState.ALL_APPS)); 163 final Integer flingForwardY = test.getFromLauncher( 164 launcher -> test.getAllAppsScroll(launcher)); 165 test.executeOnLauncher( 166 launcher -> assertTrue("flingForward() didn't scroll App Apps", 167 flingForwardY > 0)); 168 169 allApps.flingBackward(); 170 assertTrue( 171 "Launcher internal state is not All Apps", 172 test.isInState(() -> LauncherState.ALL_APPS)); 173 final Integer flingBackwardY = test.getFromLauncher( 174 launcher -> test.getAllAppsScroll(launcher)); 175 test.executeOnLauncher(launcher -> assertTrue("flingBackward() didn't scroll App Apps", 176 flingBackwardY < flingForwardY)); 177 178 // Test scrolling down to YouTube. 179 assertNotNull("All apps: can't find YouTube", allApps.getAppIcon("YouTube")); 180 // Test scrolling up to Camera. 181 assertNotNull("All apps: can't find Camera", allApps.getAppIcon("Camera")); 182 // Test failing to find a non-existing app. 183 final AllApps allAppsFinal = allApps; 184 expectFail("All apps: could find a non-existing app", 185 () -> allAppsFinal.getAppIcon("NO APP")); 186 187 assertTrue( 188 "Launcher internal state is not All Apps", 189 test.isInState(() -> LauncherState.ALL_APPS)); 190 } finally { 191 allApps.unfreeze(); 192 } 193 } 194 195 @Test 196 @PortraitLandscape testWorkspaceSwitchToAllApps()197 public void testWorkspaceSwitchToAllApps() { 198 assertNotNull("switchToAllApps() returned null", 199 mLauncher.getWorkspace().switchToAllApps()); 200 assertTrue("Launcher internal state is not All Apps", 201 isInState(() -> LauncherState.ALL_APPS)); 202 } 203 204 @Test 205 @PortraitLandscape testAllAppsSwitchToWorkspace()206 public void testAllAppsSwitchToWorkspace() { 207 assertNotNull("switchToWorkspace() returned null", 208 mLauncher.getWorkspace().switchToAllApps().switchToWorkspace()); 209 assertTrue("Launcher internal state is not Workspace", 210 isInState(() -> LauncherState.NORMAL)); 211 } 212 213 @Test 214 @PortraitLandscape testAllAppsDeadzoneForTablet()215 public void testAllAppsDeadzoneForTablet() throws Exception { 216 assumeTrue(mLauncher.isTablet()); 217 218 mLauncher.getWorkspace().switchToAllApps().dismissByTappingOutsideForTablet( 219 true /* tapRight */); 220 mLauncher.getWorkspace().switchToAllApps().dismissByTappingOutsideForTablet( 221 false /* tapRight */); 222 } 223 224 @IwTest(focusArea = "launcher") 225 @Test 226 @ScreenRecord // b/202433017 testWorkspace()227 public void testWorkspace() throws Exception { 228 // Make sure there is an instance of chrome on the hotseat 229 mLauncher.useTaplWorkspaceLayoutOnReload(); 230 clearLauncherData(); 231 232 final Workspace workspace = mLauncher.getWorkspace(); 233 234 // Test that ensureWorkspaceIsScrollable adds a page by dragging an icon there. 235 executeOnLauncher(launcher -> assertFalse("Initial workspace state is scrollable", 236 isWorkspaceScrollable(launcher))); 237 assertEquals("Initial workspace doesn't have the correct page", workspace.pagesPerScreen(), 238 workspace.getPageCount()); 239 workspace.verifyWorkspaceAppIconIsGone("Chrome app was found on empty workspace", "Chrome"); 240 workspace.ensureWorkspaceIsScrollable(); 241 242 executeOnLauncher( 243 launcher -> assertEquals( 244 "Ensuring workspace scrollable didn't switch to next screen", 245 workspace.pagesPerScreen(), getCurrentWorkspacePage(launcher))); 246 executeOnLauncher( 247 launcher -> assertTrue("ensureScrollable didn't make workspace scrollable", 248 isWorkspaceScrollable(launcher))); 249 assertNotNull("ensureScrollable didn't add Chrome app", 250 workspace.getWorkspaceAppIcon("Chrome")); 251 252 // Test flinging workspace. 253 workspace.flingBackward(); 254 assertTrue("Launcher internal state is not Home", isInState(() -> LauncherState.NORMAL)); 255 executeOnLauncher( 256 launcher -> assertEquals("Flinging back didn't switch workspace to page #0", 257 0, getCurrentWorkspacePage(launcher))); 258 259 workspace.flingForward(); 260 executeOnLauncher( 261 launcher -> assertEquals("Flinging forward didn't switch workspace to next screen", 262 workspace.pagesPerScreen(), getCurrentWorkspacePage(launcher))); 263 assertTrue("Launcher internal state is not Home", isInState(() -> LauncherState.NORMAL)); 264 265 // Test starting a workspace app. 266 final HomeAppIcon app = workspace.getWorkspaceAppIcon("Chrome"); 267 assertNotNull("No Chrome app in workspace", app); 268 } 269 runIconLaunchFromAllAppsTest(AbstractLauncherUiTest test, AllApps allApps)270 public static void runIconLaunchFromAllAppsTest(AbstractLauncherUiTest test, AllApps allApps) { 271 allApps.freeze(); 272 try { 273 final AppIcon app = allApps.getAppIcon("TestActivity7"); 274 assertNotNull("AppIcon.launch returned null", app.launch(getAppPackageName())); 275 test.executeOnLauncher(launcher -> assertTrue( 276 "Launcher activity is the top activity; expecting another activity to be the " 277 + "top one", 278 test.isInLaunchedApp(launcher))); 279 } finally { 280 allApps.unfreeze(); 281 } 282 } 283 284 @Test 285 @PortraitLandscape testAppIconLaunchFromAllAppsFromHome()286 public void testAppIconLaunchFromAllAppsFromHome() throws Exception { 287 final HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps(); 288 assertTrue("Launcher internal state is not All Apps", 289 isInState(() -> LauncherState.ALL_APPS)); 290 291 runIconLaunchFromAllAppsTest(this, allApps); 292 } 293 294 @Test 295 @PortraitLandscape testWidgets()296 public void testWidgets() throws Exception { 297 // Test opening widgets. 298 executeOnLauncher(launcher -> 299 assertTrue("Widgets is initially opened", getWidgetsView(launcher) == null)); 300 Widgets widgets = mLauncher.getWorkspace().openAllWidgets(); 301 assertNotNull("openAllWidgets() returned null", widgets); 302 widgets = mLauncher.getAllWidgets(); 303 assertNotNull("getAllWidgets() returned null", widgets); 304 executeOnLauncher(launcher -> 305 assertTrue("Widgets is not shown", getWidgetsView(launcher).isShown())); 306 executeOnLauncher(launcher -> assertEquals("Widgets is scrolled upon opening", 307 0, getWidgetsScroll(launcher))); 308 309 // Test flinging widgets. 310 widgets.flingForward(); 311 Integer flingForwardY = getFromLauncher(launcher -> getWidgetsScroll(launcher)); 312 executeOnLauncher(launcher -> assertTrue("Flinging forward didn't scroll widgets", 313 flingForwardY > 0)); 314 315 widgets.flingBackward(); 316 executeOnLauncher(launcher -> assertTrue("Flinging backward didn't scroll widgets", 317 getWidgetsScroll(launcher) < flingForwardY)); 318 319 mLauncher.goHome(); 320 waitForLauncherCondition("Widgets were not closed", 321 launcher -> getWidgetsView(launcher) == null); 322 } 323 getWidgetsScroll(Launcher launcher)324 private int getWidgetsScroll(Launcher launcher) { 325 return getWidgetsView(launcher).computeVerticalScrollOffset(); 326 } 327 isOptionsPopupVisible(Launcher launcher)328 private boolean isOptionsPopupVisible(Launcher launcher) { 329 final ArrowPopup<?> popup = launcher.getOptionsPopup(); 330 return popup != null && popup.isShown(); 331 } 332 333 @Test 334 @PortraitLandscape testLaunchMenuItem()335 public void testLaunchMenuItem() throws Exception { 336 final AllApps allApps = mLauncher.getWorkspace().switchToAllApps(); 337 allApps.freeze(); 338 try { 339 final AppIconMenu menu = allApps. 340 getAppIcon(APP_NAME). 341 openDeepShortcutMenu(); 342 343 executeOnLauncher( 344 launcher -> assertTrue("Launcher internal state didn't switch to Showing Menu", 345 isOptionsPopupVisible(launcher))); 346 347 final AppIconMenuItem menuItem = menu.getMenuItem(1); 348 assertEquals("Wrong menu item", "Shortcut 2", menuItem.getText()); 349 menuItem.launch(getAppPackageName()); 350 } finally { 351 allApps.unfreeze(); 352 } 353 } 354 355 @IwTest(focusArea = "launcher") 356 @Test 357 @PortraitLandscape 358 @ScreenRecord // b/256898879 testDragAppIcon()359 public void testDragAppIcon() throws Throwable { 360 // 1. Open all apps and wait for load complete. 361 // 2. Drag icon to homescreen. 362 // 3. Verify that the icon works on homescreen. 363 final HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps(); 364 allApps.freeze(); 365 try { 366 allApps.getAppIcon(APP_NAME).dragToWorkspace(false, false); 367 mLauncher.getWorkspace().getWorkspaceAppIcon(APP_NAME).launch(getAppPackageName()); 368 } finally { 369 allApps.unfreeze(); 370 } 371 executeOnLauncher(launcher -> assertTrue( 372 "Launcher activity is the top activity; expecting another activity to be the top " 373 + "one", 374 isInLaunchedApp(launcher))); 375 } 376 377 @Test 378 @PortraitLandscape testDragShortcut()379 public void testDragShortcut() throws Throwable { 380 // 1. Open all apps and wait for load complete. 381 // 2. Find the app and long press it to show shortcuts. 382 // 3. Press icon center until shortcuts appear 383 final HomeAllApps allApps = mLauncher 384 .getWorkspace() 385 .switchToAllApps(); 386 allApps.freeze(); 387 try { 388 final HomeAppIconMenu menu = allApps 389 .getAppIcon(APP_NAME) 390 .openDeepShortcutMenu(); 391 final HomeAppIconMenuItem menuItem0 = menu.getMenuItem(0); 392 final HomeAppIconMenuItem menuItem2 = menu.getMenuItem(2); 393 394 final HomeAppIconMenuItem menuItem; 395 396 final String expectedShortcutName = "Shortcut 3"; 397 if (menuItem0.getText().equals(expectedShortcutName)) { 398 menuItem = menuItem0; 399 } else { 400 final String shortcutName2 = menuItem2.getText(); 401 assertEquals("Wrong menu item", expectedShortcutName, shortcutName2); 402 menuItem = menuItem2; 403 } 404 405 menuItem.dragToWorkspace(false, false); 406 mLauncher.getWorkspace().getWorkspaceAppIcon(expectedShortcutName) 407 .launch(getAppPackageName()); 408 } finally { 409 allApps.unfreeze(); 410 } 411 } 412 413 @Test 414 @PortraitLandscape 415 @ScreenRecord 416 @Ignore // b/233075289 testDragToFolder()417 public void testDragToFolder() { 418 // TODO: add the use case to drag an icon to an existing folder. Currently it either fails 419 // on tablets or phones due to difference in resolution. 420 final HomeAppIcon playStoreIcon = createShortcutIfNotExist(STORE_APP_NAME, 0, 1); 421 final HomeAppIcon gmailIcon = createShortcutInCenterIfNotExist(GMAIL_APP_NAME); 422 423 FolderIcon folderIcon = gmailIcon.dragToIcon(playStoreIcon); 424 Folder folder = folderIcon.open(); 425 folder.getAppIcon(STORE_APP_NAME); 426 folder.getAppIcon(GMAIL_APP_NAME); 427 Workspace workspace = folder.close(); 428 429 workspace.verifyWorkspaceAppIconIsGone(STORE_APP_NAME + " should be moved to a folder.", 430 STORE_APP_NAME); 431 workspace.verifyWorkspaceAppIconIsGone(GMAIL_APP_NAME + " should be moved to a folder.", 432 GMAIL_APP_NAME); 433 434 final HomeAppIcon mapIcon = createShortcutInCenterIfNotExist(MAPS_APP_NAME); 435 folderIcon = mapIcon.dragToIcon(folderIcon); 436 folder = folderIcon.open(); 437 folder.getAppIcon(MAPS_APP_NAME); 438 workspace = folder.close(); 439 440 workspace.verifyWorkspaceAppIconIsGone(MAPS_APP_NAME + " should be moved to a folder.", 441 MAPS_APP_NAME); 442 } 443 444 @Test 445 @PortraitLandscape testPressBack()446 public void testPressBack() throws Exception { 447 mLauncher.getWorkspace().switchToAllApps(); 448 mLauncher.pressBack(); 449 mLauncher.getWorkspace(); 450 waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL); 451 452 startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR)); 453 mLauncher.pressBack(); 454 mLauncher.getWorkspace(); 455 waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL); 456 } 457 458 @Test 459 @PortraitLandscape testDragAndCancelAppIcon()460 public void testDragAndCancelAppIcon() { 461 final HomeAppIcon homeAppIcon = createShortcutInCenterIfNotExist(GMAIL_APP_NAME); 462 Point positionBeforeDrag = 463 mLauncher.getWorkspace().getWorkspaceIconsPositions().get(GMAIL_APP_NAME); 464 assertNotNull("App not found in Workspace before dragging.", positionBeforeDrag); 465 466 mLauncher.getWorkspace().dragAndCancelAppIcon(homeAppIcon); 467 468 Point positionAfterDrag = 469 mLauncher.getWorkspace().getWorkspaceIconsPositions().get(GMAIL_APP_NAME); 470 assertNotNull("App not found in Workspace after dragging.", positionAfterDrag); 471 assertEquals("App not returned to same position in Workspace after drag & cancel", 472 positionBeforeDrag, positionAfterDrag); 473 } 474 475 @Test 476 @PortraitLandscape testDeleteFromWorkspace()477 public void testDeleteFromWorkspace() throws Exception { 478 // test delete both built-in apps and user-installed app from workspace 479 for (String appName : new String[]{"Gmail", "Play Store", APP_NAME}) { 480 final HomeAppIcon homeAppIcon = createShortcutInCenterIfNotExist(appName); 481 Workspace workspace = mLauncher.getWorkspace().deleteAppIcon(homeAppIcon); 482 workspace.verifyWorkspaceAppIconIsGone( 483 appName + " app was found after being deleted from workspace", 484 appName); 485 } 486 } 487 verifyAppUninstalledFromAllApps(Workspace workspace, String appName)488 private void verifyAppUninstalledFromAllApps(Workspace workspace, String appName) { 489 final HomeAllApps allApps = workspace.switchToAllApps(); 490 allApps.freeze(); 491 try { 492 assertNull(appName + " app was found on all apps after being uninstalled", 493 allApps.tryGetAppIcon(appName)); 494 } finally { 495 allApps.unfreeze(); 496 } 497 } 498 499 @Test 500 @PortraitLandscape testUninstallFromWorkspace()501 public void testUninstallFromWorkspace() throws Exception { 502 installDummyAppAndWaitForUIUpdate(); 503 try { 504 verifyAppUninstalledFromAllApps( 505 createShortcutInCenterIfNotExist(DUMMY_APP_NAME).uninstall(), DUMMY_APP_NAME); 506 } finally { 507 TestUtil.uninstallDummyApp(); 508 } 509 } 510 511 @Test 512 @PortraitLandscape testUninstallFromAllApps()513 public void testUninstallFromAllApps() throws Exception { 514 installDummyAppAndWaitForUIUpdate(); 515 try { 516 Workspace workspace = mLauncher.getWorkspace(); 517 final HomeAllApps allApps = workspace.switchToAllApps(); 518 allApps.freeze(); 519 try { 520 workspace = allApps.getAppIcon(DUMMY_APP_NAME).uninstall(); 521 // After the toast clears, then the model tries to commit the uninstall transaction 522 mLauncher.waitForModelQueueCleared(); 523 } finally { 524 allApps.unfreeze(); 525 } 526 verifyAppUninstalledFromAllApps(workspace, DUMMY_APP_NAME); 527 } finally { 528 TestUtil.uninstallDummyApp(); 529 } 530 } 531 532 @Test 533 @PortraitLandscape testDragAppIconToWorkspaceCell()534 public void testDragAppIconToWorkspaceCell() throws Exception { 535 long startTime, endTime, elapsedTime; 536 Point[] targets = getCornersAndCenterPositions(); 537 538 for (Point target : targets) { 539 startTime = SystemClock.uptimeMillis(); 540 final HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps(); 541 allApps.freeze(); 542 try { 543 allApps.getAppIcon(APP_NAME).dragToWorkspace(target.x, target.y); 544 } finally { 545 allApps.unfreeze(); 546 } 547 // Reset the workspace for the next shortcut creation. 548 initialize(this); 549 endTime = SystemClock.uptimeMillis(); 550 elapsedTime = endTime - startTime; 551 Log.d("testDragAppIconToWorkspaceCellTime", 552 "Milliseconds taken to drag app icon to workspace cell: " + elapsedTime); 553 } 554 555 // test to move a shortcut to other cell. 556 final HomeAppIcon launcherTestAppIcon = createShortcutInCenterIfNotExist(APP_NAME); 557 for (Point target : targets) { 558 startTime = SystemClock.uptimeMillis(); 559 launcherTestAppIcon.dragToWorkspace(target.x, target.y); 560 endTime = SystemClock.uptimeMillis(); 561 elapsedTime = endTime - startTime; 562 Log.d("testDragAppIconToWorkspaceCellTime", 563 "Milliseconds taken to move shortcut to other cell: " + elapsedTime); 564 } 565 } 566 567 @Test getIconsPosition_afterIconRemoved_notContained()568 public void getIconsPosition_afterIconRemoved_notContained() throws IOException { 569 Point[] gridPositions = getCornersAndCenterPositions(); 570 createShortcutIfNotExist(STORE_APP_NAME, gridPositions[0]); 571 createShortcutIfNotExist(MAPS_APP_NAME, gridPositions[1]); 572 installDummyAppAndWaitForUIUpdate(); 573 try { 574 createShortcutIfNotExist(DUMMY_APP_NAME, gridPositions[2]); 575 Map<String, Point> initialPositions = 576 mLauncher.getWorkspace().getWorkspaceIconsPositions(); 577 assertThat(initialPositions.keySet()) 578 .containsAtLeast(DUMMY_APP_NAME, MAPS_APP_NAME, STORE_APP_NAME); 579 580 mLauncher.getWorkspace().getWorkspaceAppIcon(DUMMY_APP_NAME).uninstall(); 581 mLauncher.getWorkspace().verifyWorkspaceAppIconIsGone( 582 DUMMY_APP_NAME + " was expected to disappear after uninstall.", DUMMY_APP_NAME); 583 584 Map<String, Point> finalPositions = 585 mLauncher.getWorkspace().getWorkspaceIconsPositions(); 586 assertThat(finalPositions).doesNotContainKey(DUMMY_APP_NAME); 587 } finally { 588 TestUtil.uninstallDummyApp(); 589 } 590 } 591 592 @Test 593 @PortraitLandscape testDragShortcutToWorkspaceCell()594 public void testDragShortcutToWorkspaceCell() throws Exception { 595 Point[] targets = getCornersAndCenterPositions(); 596 597 for (Point target : targets) { 598 final HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps(); 599 allApps.freeze(); 600 try { 601 allApps.getAppIcon(APP_NAME) 602 .openDeepShortcutMenu() 603 .getMenuItem(0) 604 .dragToWorkspace(target.x, target.y); 605 } finally { 606 allApps.unfreeze(); 607 } 608 } 609 } 610 611 @Test 612 @PortraitLandscape testAddDeleteShortcutOnHotseat()613 public void testAddDeleteShortcutOnHotseat() { 614 mLauncher.getWorkspace() 615 .deleteAppIcon(mLauncher.getWorkspace().getHotseatAppIcon(0)) 616 .switchToAllApps() 617 .getAppIcon(APP_NAME) 618 .dragToHotseat(0); 619 mLauncher.getWorkspace().deleteAppIcon( 620 mLauncher.getWorkspace().getHotseatAppIcon(APP_NAME)); 621 } 622 installDummyAppAndWaitForUIUpdate()623 private void installDummyAppAndWaitForUIUpdate() throws IOException { 624 TestUtil.installDummyApp(); 625 // Wait for model thread completion as it may be processing 626 // the install event from the SystemService 627 mLauncher.waitForModelQueueCleared(); 628 // Wait for Launcher UI thread completion, as it may be processing updating the UI in 629 // response to the model update. Not that `waitForLauncherInitialized` is just a proxy 630 // method, we can use any method which touches Launcher UI thread, 631 mLauncher.waitForLauncherInitialized(); 632 } 633 634 /** 635 * @return List of workspace grid coordinates. Those are not pixels. See {@link 636 * Workspace#getIconGridDimensions()} 637 */ getCornersAndCenterPositions()638 private Point[] getCornersAndCenterPositions() { 639 final Point dimensions = mLauncher.getWorkspace().getIconGridDimensions(); 640 return new Point[]{ 641 new Point(0, 1), 642 new Point(0, dimensions.y - 2), 643 new Point(dimensions.x - 1, 1), 644 new Point(dimensions.x - 1, dimensions.y - 2), 645 new Point(dimensions.x / 2, dimensions.y / 2) 646 }; 647 } 648 getAppPackageName()649 public static String getAppPackageName() { 650 return getInstrumentation().getContext().getPackageName(); 651 } 652 653 @Test testGetAppIconName()654 public void testGetAppIconName() { 655 HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps(); 656 allApps.freeze(); 657 try { 658 HomeAppIcon icon = allApps.getAppIcon(APP_NAME); 659 assertEquals("Wrong app icon name.", icon.getIconName(), APP_NAME); 660 } finally { 661 allApps.unfreeze(); 662 } 663 } 664 } 665