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 android.graphics.Point; 20 import android.graphics.Rect; 21 22 import androidx.annotation.NonNull; 23 import androidx.test.uiautomator.UiObject2; 24 25 import java.util.function.Supplier; 26 27 /** 28 * App icon on the workspace or all apps. 29 */ 30 public abstract class HomeAppIcon extends AppIcon implements FolderDragTarget, WorkspaceDragSource { 31 32 private final String mAppName; 33 HomeAppIcon(LauncherInstrumentation launcher, UiObject2 icon)34 HomeAppIcon(LauncherInstrumentation launcher, UiObject2 icon) { 35 super(launcher, icon); 36 mAppName = icon.getText(); 37 } 38 39 /** 40 * Drag the AppIcon to the given position of other icon. The drag must result in a folder. 41 * 42 * @param target the destination icon. 43 */ 44 @NonNull dragToIcon(FolderDragTarget target)45 public FolderIcon dragToIcon(FolderDragTarget target) { 46 try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); 47 LauncherInstrumentation.Closable c = mLauncher.addContextLayer("want to drag icon")) { 48 final Rect dropBounds = target.getDropLocationBounds(); 49 Workspace.dragIconToWorkspace( 50 mLauncher, this, 51 () -> { 52 final Rect bounds = target.getDropLocationBounds(); 53 return new Point(bounds.centerX(), bounds.centerY()); 54 }); 55 FolderIcon result = target.getTargetFolder(dropBounds); 56 mLauncher.assertTrue("Can't find the target folder.", result != null); 57 return result; 58 } 59 } 60 61 /** This method requires public access, however should not be called in tests. */ 62 @Override getDropLocationBounds()63 public Rect getDropLocationBounds() { 64 return mLauncher.getVisibleBounds(mObject); 65 } 66 67 /** This method requires public access, however should not be called in tests. */ 68 @Override getTargetFolder(Rect bounds)69 public FolderIcon getTargetFolder(Rect bounds) { 70 for (FolderIcon folderIcon : mLauncher.getWorkspace().getFolderIcons()) { 71 final Rect folderIconBounds = folderIcon.getDropLocationBounds(); 72 if (bounds.contains(folderIconBounds.centerX(), folderIconBounds.centerY())) { 73 return folderIcon; 74 } 75 } 76 return null; 77 } 78 79 @Override openDeepShortcutMenu()80 public HomeAppIconMenu openDeepShortcutMenu() { 81 return (HomeAppIconMenu) super.openDeepShortcutMenu(); 82 } 83 84 @Override createMenu(UiObject2 menu)85 protected HomeAppIconMenu createMenu(UiObject2 menu) { 86 return new HomeAppIconMenu(mLauncher, menu); 87 } 88 89 /** 90 * Uninstall the appIcon by dragging it to the 'uninstall' drop point of the drop_target_bar. 91 * 92 * @return validated workspace after the existing appIcon being uninstalled. 93 */ uninstall()94 public Workspace uninstall() { 95 try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); 96 LauncherInstrumentation.Closable c = mLauncher.addContextLayer( 97 "uninstalling app icon")) { 98 return Workspace.uninstallAppIcon( 99 mLauncher, this, 100 this::addExpectedEventsForLongClick 101 ); 102 } 103 } 104 105 /** 106 * Drag an object to the given cell in hotseat. The target cell should be expected to be empty. 107 * 108 * @param cellInd zero based index number of the hotseat cells. 109 * @return the workspace app icon. 110 */ 111 @NonNull dragToHotseat(int cellInd)112 public WorkspaceAppIcon dragToHotseat(int cellInd) { 113 try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); 114 LauncherInstrumentation.Closable c = mLauncher.addContextLayer( 115 String.format("want to drag the icon to hotseat cell %d", cellInd)) 116 ) { 117 final Supplier<Point> dest = () -> Workspace.getHotseatCellCenter(mLauncher, cellInd); 118 119 Workspace.dragIconToHotseat( 120 mLauncher, 121 this, 122 dest, 123 () -> addExpectedEventsForLongClick(), 124 /*expectDropEvents= */ null); 125 try (LauncherInstrumentation.Closable ignore = mLauncher.addContextLayer("dragged")) { 126 WorkspaceAppIcon appIcon = 127 (WorkspaceAppIcon) mLauncher.getWorkspace().getHotseatAppIcon(mAppName); 128 mLauncher.assertTrue( 129 String.format("The %s icon should be in the hotseat cell %d.", mAppName, 130 cellInd), 131 appIcon.isInHotseatCell(cellInd)); 132 return appIcon; 133 } 134 } 135 } 136 137 /** This method requires public access, however should not be called in tests. */ 138 @Override getLaunchable()139 public Launchable getLaunchable() { 140 return this; 141 } 142 isInHotseatCell(int cellInd)143 boolean isInHotseatCell(int cellInd) { 144 final Point center = Workspace.getHotseatCellCenter(mLauncher, cellInd); 145 return mObject.getVisibleBounds().contains(center.x, center.y); 146 } 147 } 148