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 IconDragTarget, 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(IconDragTarget target)45 public FolderIcon dragToIcon(IconDragTarget 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 }, false); 55 FolderIcon result = target.getTargetIcon(dropBounds); 56 mLauncher.assertTrue("Can't find the target folder.", result != null); 57 return result; 58 } 59 } 60 61 /** 62 * Drag the AppIcon to the given position of a folder icon, and then inside that folder. 63 * 64 * @param target the destination folder. 65 */ 66 @NonNull dragToFolder(IconDragTarget target)67 public Folder dragToFolder(IconDragTarget target) { 68 try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); 69 LauncherInstrumentation.Closable c = mLauncher.addContextLayer("want to drag icon")) { 70 Workspace.dragIconToWorkspace( 71 mLauncher, this, 72 () -> { 73 final Rect bounds = target.getDropLocationBounds(); 74 return new Point(bounds.centerX(), bounds.centerY()); 75 }, /* isDraggingToFolder */ true); 76 } 77 return new Folder(mLauncher); 78 } 79 80 81 /** This method requires public access, however should not be called in tests. */ 82 @Override getDropLocationBounds()83 public Rect getDropLocationBounds() { 84 return mLauncher.getVisibleBounds(mObject); 85 } 86 87 /** This method requires public access, however should not be called in tests. */ 88 @Override getTargetIcon(Rect bounds)89 public FolderIcon getTargetIcon(Rect bounds) { 90 for (FolderIcon folderIcon : mLauncher.getWorkspace().getFolderIcons()) { 91 final Rect folderIconBounds = folderIcon.getDropLocationBounds(); 92 if (bounds.contains(folderIconBounds.centerX(), folderIconBounds.centerY())) { 93 return folderIcon; 94 } 95 } 96 return null; 97 } 98 99 @Override openDeepShortcutMenu()100 public HomeAppIconMenu openDeepShortcutMenu() { 101 return (HomeAppIconMenu) super.openDeepShortcutMenu(); 102 } 103 104 @Override createMenu(UiObject2 menu)105 protected HomeAppIconMenu createMenu(UiObject2 menu) { 106 return new HomeAppIconMenu(mLauncher, menu); 107 } 108 109 /** 110 * Uninstall the appIcon by dragging it to the 'uninstall' drop point of the drop_target_bar. 111 * 112 * @return validated workspace after the existing appIcon being uninstalled. 113 */ uninstall()114 public Workspace uninstall() { 115 try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); 116 LauncherInstrumentation.Closable c = mLauncher.addContextLayer( 117 "uninstalling app icon")) { 118 return Workspace.uninstallAppIcon( 119 mLauncher, this, 120 this::addExpectedEventsForLongClick 121 ); 122 } 123 } 124 125 /** 126 * Drag an object to the given cell in hotseat. The target cell should be expected to be empty. 127 * 128 * @param cellInd zero based index number of the hotseat cells. 129 * @return the workspace app icon. 130 */ 131 @NonNull dragToHotseat(int cellInd)132 public WorkspaceAppIcon dragToHotseat(int cellInd) { 133 try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); 134 LauncherInstrumentation.Closable c = mLauncher.addContextLayer( 135 String.format("want to drag the icon to hotseat cell %d", cellInd)) 136 ) { 137 final Supplier<Point> dest = () -> Workspace.getHotseatCellCenter(mLauncher, cellInd); 138 139 Workspace.dragIconToHotseat( 140 mLauncher, 141 this, 142 dest, 143 () -> addExpectedEventsForLongClick(), 144 /*expectDropEvents= */ null); 145 try (LauncherInstrumentation.Closable ignore = mLauncher.addContextLayer("dragged")) { 146 WorkspaceAppIcon appIcon = 147 (WorkspaceAppIcon) mLauncher.getWorkspace().getHotseatAppIcon(mAppName); 148 mLauncher.assertTrue( 149 String.format("The %s icon should be in the hotseat cell %d.", mAppName, 150 cellInd), 151 appIcon.isInHotseatCell(cellInd)); 152 return appIcon; 153 } 154 } 155 } 156 157 /** This method requires public access, however should not be called in tests. */ 158 @Override getLaunchable()159 public Launchable getLaunchable() { 160 return this; 161 } 162 isInHotseatCell(int cellInd)163 boolean isInHotseatCell(int cellInd) { 164 final Point center = Workspace.getHotseatCellCenter(mLauncher, cellInd); 165 return mObject.getVisibleBounds().contains(center.x, center.y); 166 } 167 } 168