1 /* 2 * Copyright (C) 2024 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.popup; 18 19 import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT; 20 21 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; 22 import static com.android.launcher3.Flags.FLAG_ENABLE_PRIVATE_SPACE; 23 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_ALL_APPS; 24 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION; 25 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION; 26 import static com.android.launcher3.model.data.WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI; 27 28 import static org.junit.Assert.assertFalse; 29 import static org.junit.Assert.assertNotNull; 30 import static org.junit.Assert.assertNull; 31 import static org.junit.Assert.assertTrue; 32 import static org.mockito.ArgumentMatchers.any; 33 import static org.mockito.Mockito.atLeast; 34 import static org.mockito.Mockito.doReturn; 35 import static org.mockito.Mockito.times; 36 import static org.mockito.Mockito.verify; 37 import static org.mockito.Mockito.when; 38 39 import android.content.ComponentName; 40 import android.content.Intent; 41 import android.content.pm.ApplicationInfo; 42 import android.content.pm.LauncherActivityInfo; 43 import android.content.pm.LauncherApps; 44 import android.os.Process; 45 import android.os.UserHandle; 46 import android.platform.test.annotations.DisableFlags; 47 import android.platform.test.annotations.EnableFlags; 48 import android.platform.test.flag.junit.SetFlagsRule; 49 import android.view.View; 50 51 import androidx.test.annotation.UiThreadTest; 52 import androidx.test.filters.SmallTest; 53 54 import com.android.launcher3.allapps.PrivateProfileManager; 55 import com.android.launcher3.model.data.AppInfo; 56 import com.android.launcher3.model.data.ItemInfo; 57 import com.android.launcher3.model.data.WorkspaceItemInfo; 58 import com.android.launcher3.pm.UserCache; 59 import com.android.launcher3.util.ApiWrapper; 60 import com.android.launcher3.util.ComponentKey; 61 import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext; 62 import com.android.launcher3.util.LauncherMultivalentJUnit; 63 import com.android.launcher3.util.TestSandboxModelContextWrapper; 64 import com.android.launcher3.util.UserIconInfo; 65 import com.android.launcher3.views.BaseDragLayer; 66 67 import org.junit.After; 68 import org.junit.Assert; 69 import org.junit.Before; 70 import org.junit.Rule; 71 import org.junit.Test; 72 import org.junit.runner.RunWith; 73 import org.mockito.Mock; 74 import org.mockito.MockitoAnnotations; 75 76 import java.util.ArrayList; 77 78 @SmallTest 79 @RunWith(LauncherMultivalentJUnit.class) 80 public class SystemShortcutTest { 81 @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT); 82 private static final UserHandle PRIVATE_HANDLE = new UserHandle(11); 83 private static final UserHandle MAIN_HANDLE = Process.myUserHandle(); 84 private View mView; 85 private ItemInfo mItemInfo; 86 private TestSandboxModelContextWrapper mTestContext; 87 private final SandboxModelContext mSandboxContext = new SandboxModelContext(); 88 private PrivateProfileManager mPrivateProfileManager; 89 private PopupDataProvider mPopupDataProvider; 90 private AppInfo mAppInfo; 91 @Mock UserCache mUserCache; 92 @Mock ApiWrapper mApiWrapper; 93 @Mock BaseDragLayer mBaseDragLayer; 94 @Mock UserIconInfo mUserIconInfo; 95 @Mock LauncherActivityInfo mLauncherActivityInfo; 96 @Mock ApplicationInfo mApplicationInfo; 97 @Mock Intent mIntent; 98 99 @Before setUp()100 public void setUp() { 101 MockitoAnnotations.initMocks(this); 102 mSandboxContext.putObject(UserCache.INSTANCE, mUserCache); 103 mSandboxContext.putObject(ApiWrapper.INSTANCE, mApiWrapper); 104 mTestContext = new TestSandboxModelContextWrapper(mSandboxContext); 105 mView = new View(mSandboxContext); 106 spyOn(mTestContext); 107 spyOn(mSandboxContext); 108 doReturn(mBaseDragLayer).when(mTestContext).getDragLayer(); 109 110 mItemInfo = new ItemInfo(); 111 112 LauncherApps mLauncherApps = mSandboxContext.spyService(LauncherApps.class); 113 doReturn(mLauncherActivityInfo).when(mLauncherApps).resolveActivity(any(), any()); 114 when(mLauncherActivityInfo.getApplicationInfo()).thenReturn(mApplicationInfo); 115 116 when(mUserCache.getUserInfo(any())).thenReturn(mUserIconInfo); 117 when(mBaseDragLayer.getChildCount()).thenReturn(0); 118 mPrivateProfileManager = mTestContext.getAppsView().getPrivateProfileManager(); 119 spyOn(mPrivateProfileManager); 120 when(mPrivateProfileManager.getProfileUser()).thenReturn(PRIVATE_HANDLE); 121 122 mPopupDataProvider = mTestContext.getPopupDataProvider(); 123 spyOn(mPopupDataProvider); 124 } 125 126 @After tearDown()127 public void tearDown() { 128 mSandboxContext.onDestroy(); 129 } 130 131 @Test testWidgetsForNullComponentName()132 public void testWidgetsForNullComponentName() { 133 assertNull(mItemInfo.getTargetComponent()); 134 SystemShortcut systemShortcut = SystemShortcut.WIDGETS 135 .getShortcut(mTestContext, mItemInfo, mView); 136 assertNull(systemShortcut); 137 } 138 139 @Test testWidgetsForEmptyWidgetList()140 public void testWidgetsForEmptyWidgetList() { 141 mAppInfo = new AppInfo(); 142 mAppInfo.componentName = new ComponentName(mTestContext, getClass()); 143 assertNotNull(mAppInfo.getTargetComponent()); 144 doReturn(new ArrayList<>()).when(mPopupDataProvider).getWidgetsForPackageUser(any()); 145 spyOn(mAppInfo); 146 SystemShortcut systemShortcut = SystemShortcut.WIDGETS 147 .getShortcut(mTestContext, mAppInfo, mView); 148 verify(mAppInfo, times(2)).getTargetComponent(); 149 assertNull(systemShortcut); 150 } 151 152 @Test testAppInfoShortcut()153 public void testAppInfoShortcut() { 154 mAppInfo = new AppInfo(); 155 mAppInfo.componentName = new ComponentName(mTestContext, getClass()); 156 SystemShortcut systemShortcut = SystemShortcut.APP_INFO 157 .getShortcut(mTestContext, mAppInfo, mView); 158 assertNotNull(systemShortcut); 159 } 160 161 162 @Test testDontSuggestAppForNonPredictedItem()163 public void testDontSuggestAppForNonPredictedItem() { 164 assertFalse(mItemInfo.isPredictedItem()); 165 SystemShortcut systemShortcut = SystemShortcut.DONT_SUGGEST_APP 166 .getShortcut(mTestContext, mItemInfo, mView); 167 assertNull(systemShortcut); 168 } 169 170 @Test testDontSuggestAppForPredictedItem()171 public void testDontSuggestAppForPredictedItem() { 172 mAppInfo = new AppInfo(); 173 mAppInfo.componentName = new ComponentName(mTestContext, getClass()); 174 mAppInfo.container = CONTAINER_HOTSEAT_PREDICTION; 175 assertTrue(mAppInfo.isPredictedItem()); 176 SystemShortcut systemShortcut = SystemShortcut.DONT_SUGGEST_APP 177 .getShortcut(mTestContext, mAppInfo, mView); 178 assertNotNull(systemShortcut); 179 systemShortcut.onClick(mView); 180 } 181 182 @Test testPrivateProfileInstallwithTargetComponentNull()183 public void testPrivateProfileInstallwithTargetComponentNull() { 184 assertNull(mItemInfo.getTargetComponent()); 185 SystemShortcut systemShortcut = SystemShortcut.PRIVATE_PROFILE_INSTALL 186 .getShortcut(mTestContext, mItemInfo, mView); 187 assertNull(systemShortcut); 188 } 189 190 @Test testPrivateProfileInstallNotAllAppsContainer()191 public void testPrivateProfileInstallNotAllAppsContainer() { 192 mAppInfo = new AppInfo(); 193 mAppInfo.componentName = new ComponentName(mTestContext, getClass()); 194 mAppInfo.container = CONTAINER_HOTSEAT_PREDICTION; 195 196 assertNotNull(mAppInfo.getTargetComponent()); 197 assertFalse(mAppInfo.getContainerInfo().hasAllAppsContainer()); 198 199 SystemShortcut systemShortcut = SystemShortcut.PRIVATE_PROFILE_INSTALL 200 .getShortcut(mTestContext, mAppInfo, mView); 201 assertNull(systemShortcut); 202 } 203 204 @Test testPrivateProfileInstallNullPrivateProfileManager()205 public void testPrivateProfileInstallNullPrivateProfileManager() { 206 mAppInfo = new AppInfo(); 207 mAppInfo.componentName = new ComponentName(mTestContext, getClass()); 208 mAppInfo.container = CONTAINER_ALL_APPS; 209 mPrivateProfileManager = null; 210 211 assertNotNull(mAppInfo.getTargetComponent()); 212 assertTrue(mAppInfo.getContainerInfo().hasAllAppsContainer()); 213 assertNull(mPrivateProfileManager); 214 215 SystemShortcut systemShortcut = SystemShortcut.PRIVATE_PROFILE_INSTALL 216 .getShortcut(mTestContext, mAppInfo, mView); 217 assertNull(systemShortcut); 218 } 219 220 @Test testPrivateProfileInstallPrivateProfileManagerDisabled()221 public void testPrivateProfileInstallPrivateProfileManagerDisabled() { 222 mAppInfo = new AppInfo(); 223 mAppInfo.componentName = new ComponentName(mTestContext, getClass()); 224 mAppInfo.container = CONTAINER_ALL_APPS; 225 226 assertNotNull(mPrivateProfileManager); 227 assertNotNull(mAppInfo.getTargetComponent()); 228 assertTrue(mAppInfo.getContainerInfo().hasAllAppsContainer()); 229 230 when(mPrivateProfileManager.isEnabled()).thenReturn(false); 231 SystemShortcut systemShortcut = SystemShortcut.PRIVATE_PROFILE_INSTALL 232 .getShortcut(mTestContext, mAppInfo, mView); 233 assertNull(systemShortcut); 234 } 235 236 @Test testPrivateProfileInstallNullPrivateProfileUser()237 public void testPrivateProfileInstallNullPrivateProfileUser() { 238 mAppInfo = new AppInfo(); 239 mAppInfo.componentName = new ComponentName(mTestContext, getClass()); 240 mAppInfo.container = CONTAINER_ALL_APPS; 241 when(mPrivateProfileManager.getProfileUser()).thenReturn(null); 242 243 assertNotNull(mPrivateProfileManager); 244 assertNotNull(mAppInfo.getTargetComponent()); 245 assertTrue(mAppInfo.getContainerInfo().hasAllAppsContainer()); 246 assertNull(mPrivateProfileManager.getProfileUser()); 247 248 SystemShortcut systemShortcut = SystemShortcut.PRIVATE_PROFILE_INSTALL 249 .getShortcut(mTestContext, mAppInfo, mView); 250 251 assertNull(systemShortcut); 252 } 253 254 @Test testPrivateProfileInstallNonNullPrivateProfileUser()255 public void testPrivateProfileInstallNonNullPrivateProfileUser() { 256 mAppInfo = new AppInfo(); 257 mAppInfo.componentName = new ComponentName(mTestContext, getClass()); 258 mAppInfo.container = CONTAINER_ALL_APPS; 259 when(mPrivateProfileManager.isEnabled()).thenReturn(true); 260 when(mPrivateProfileManager.getProfileUser()).thenReturn(PRIVATE_HANDLE); 261 262 assertNotNull(mAppInfo.getTargetComponent()); 263 assertTrue(mAppInfo.getContainerInfo().hasAllAppsContainer()); 264 assertNotNull(mPrivateProfileManager); 265 assertNotNull(mPrivateProfileManager.getProfileUser()); 266 assertNull(mTestContext.getAppsView().getAppsStore().getApp( 267 new ComponentKey(mAppInfo.getTargetComponent(), PRIVATE_HANDLE))); 268 269 SystemShortcut systemShortcut = SystemShortcut.PRIVATE_PROFILE_INSTALL 270 .getShortcut(mTestContext, mAppInfo, mView); 271 272 verify(mPrivateProfileManager, atLeast(1)).isEnabled(); 273 assertNotNull(systemShortcut); 274 } 275 276 @Test testInstallGetShortcutWithNonWorkSpaceItemInfo()277 public void testInstallGetShortcutWithNonWorkSpaceItemInfo() { 278 SystemShortcut systemShortcut = SystemShortcut.INSTALL.getShortcut( 279 mTestContext, mItemInfo, mView); 280 Assert.assertNull(systemShortcut); 281 } 282 283 @Test 284 @UiThreadTest testInstallGetShortcutWithWorkSpaceItemInfo()285 public void testInstallGetShortcutWithWorkSpaceItemInfo() { 286 mAppInfo = new AppInfo(); 287 mAppInfo.componentName = new ComponentName(mTestContext, getClass()); 288 mAppInfo.intent = mIntent; 289 WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo(mAppInfo); 290 workspaceItemInfo.status = FLAG_SUPPORTS_WEB_UI; 291 SystemShortcut systemShortcut = SystemShortcut.INSTALL.getShortcut( 292 mTestContext, workspaceItemInfo, mView); 293 Assert.assertNotNull(systemShortcut); 294 } 295 296 297 @Test 298 @DisableFlags(FLAG_ENABLE_PRIVATE_SPACE) testUninstallGetShortcutWithPrivateSpaceOff()299 public void testUninstallGetShortcutWithPrivateSpaceOff() { 300 SystemShortcut systemShortcut = SystemShortcut.UNINSTALL_APP.getShortcut( 301 mTestContext, null, mView); 302 Assert.assertNull(systemShortcut); 303 } 304 305 @Test 306 @EnableFlags(FLAG_ENABLE_PRIVATE_SPACE) testUninstallGetShortcutWithNonPrivateItemInfo()307 public void testUninstallGetShortcutWithNonPrivateItemInfo() { 308 mAppInfo = new AppInfo(); 309 mAppInfo.user = MAIN_HANDLE; 310 when(mUserIconInfo.isPrivate()).thenReturn(false); 311 312 SystemShortcut systemShortcut = SystemShortcut.UNINSTALL_APP.getShortcut( 313 mTestContext, mAppInfo, mView); 314 verify(mUserIconInfo).isPrivate(); 315 Assert.assertNull(systemShortcut); 316 } 317 318 @Test 319 @EnableFlags(FLAG_ENABLE_PRIVATE_SPACE) testUninstallGetShortcutWithSystemItemInfo()320 public void testUninstallGetShortcutWithSystemItemInfo() { 321 mAppInfo = new AppInfo(); 322 mAppInfo.user = PRIVATE_HANDLE; 323 mAppInfo.itemType = ITEM_TYPE_APPLICATION; 324 mAppInfo.intent = mIntent; 325 mAppInfo.componentName = new ComponentName(mTestContext, getClass()); 326 when(mLauncherActivityInfo.getComponentName()).thenReturn(mAppInfo.componentName); 327 when(mUserIconInfo.isPrivate()).thenReturn(true); 328 // System App 329 mApplicationInfo.flags = 1; 330 331 SystemShortcut systemShortcut = SystemShortcut.UNINSTALL_APP.getShortcut( 332 mTestContext, mAppInfo, mView); 333 verify(mLauncherActivityInfo, times(0)).getComponentName(); 334 Assert.assertNull(systemShortcut); 335 } 336 337 @Test 338 @EnableFlags(FLAG_ENABLE_PRIVATE_SPACE) testUninstallGetShortcutWithPrivateItemInfo()339 public void testUninstallGetShortcutWithPrivateItemInfo() { 340 mAppInfo = new AppInfo(); 341 mAppInfo.user = PRIVATE_HANDLE; 342 mAppInfo.itemType = ITEM_TYPE_APPLICATION; 343 mAppInfo.intent = mIntent; 344 mAppInfo.componentName = new ComponentName(mTestContext, getClass()); 345 when(mUserIconInfo.isPrivate()).thenReturn(true); 346 when(mLauncherActivityInfo.getComponentName()).thenReturn(mAppInfo.componentName); 347 // 3rd party app, not system app. 348 mApplicationInfo.flags = 0; 349 350 SystemShortcut systemShortcut = SystemShortcut.UNINSTALL_APP.getShortcut( 351 mTestContext, mAppInfo, mView); 352 353 verify(mLauncherActivityInfo).getComponentName(); 354 Assert.assertNotNull(systemShortcut); 355 356 systemShortcut.onClick(mView); 357 verify(mSandboxContext).startActivity(any()); 358 } 359 } 360