1 /* 2 * Copyright (C) 2023 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.allapps; 18 19 import static androidx.test.core.app.ApplicationProvider.getApplicationContext; 20 21 import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_PRIVATE_SPACE_HEADER; 22 import static com.android.launcher3.allapps.UserProfileManager.STATE_DISABLED; 23 import static com.android.launcher3.allapps.UserProfileManager.STATE_ENABLED; 24 import static com.android.launcher3.allapps.UserProfileManager.STATE_TRANSITION; 25 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; 26 27 import static org.junit.Assert.assertEquals; 28 import static org.junit.Assert.assertTrue; 29 import static org.mockito.AdditionalAnswers.answer; 30 import static org.mockito.ArgumentMatchers.any; 31 import static org.mockito.Mockito.doAnswer; 32 import static org.mockito.Mockito.doNothing; 33 import static org.mockito.Mockito.doReturn; 34 import static org.mockito.Mockito.spy; 35 import static org.mockito.Mockito.when; 36 37 import android.content.ComponentName; 38 import android.content.Context; 39 import android.content.Intent; 40 import android.graphics.Bitmap; 41 import android.graphics.Canvas; 42 import android.graphics.drawable.BitmapDrawable; 43 import android.graphics.drawable.Drawable; 44 import android.os.Process; 45 import android.os.UserHandle; 46 import android.os.UserManager; 47 import android.view.LayoutInflater; 48 import android.view.View; 49 import android.widget.ImageButton; 50 import android.widget.ImageView; 51 import android.widget.LinearLayout; 52 import android.widget.RelativeLayout; 53 import android.widget.TextView; 54 55 import androidx.test.filters.SmallTest; 56 import androidx.test.runner.AndroidJUnit4; 57 58 import com.android.launcher3.R; 59 import com.android.launcher3.logging.StatsLogManager; 60 import com.android.launcher3.model.data.AppInfo; 61 import com.android.launcher3.pm.UserCache; 62 import com.android.launcher3.util.ActivityContextWrapper; 63 import com.android.launcher3.util.UserIconInfo; 64 65 import org.junit.Before; 66 import org.junit.Test; 67 import org.junit.runner.RunWith; 68 import org.mockito.Mock; 69 import org.mockito.MockitoAnnotations; 70 71 import java.util.ArrayList; 72 import java.util.Arrays; 73 import java.util.List; 74 import java.util.function.Predicate; 75 76 @SmallTest 77 @RunWith(AndroidJUnit4.class) 78 public class PrivateSpaceHeaderViewTest { 79 80 private static final UserHandle MAIN_HANDLE = Process.myUserHandle(); 81 private static final UserHandle PRIVATE_HANDLE = new UserHandle(11); 82 private static final UserIconInfo MAIN_ICON_INFO = 83 new UserIconInfo(MAIN_HANDLE, UserIconInfo.TYPE_MAIN); 84 private static final UserIconInfo PRIVATE_ICON_INFO = 85 new UserIconInfo(PRIVATE_HANDLE, UserIconInfo.TYPE_PRIVATE); 86 private static final String CAMERA_PACKAGE_NAME = "com.android.launcher3.tests.camera"; 87 private static final int CONTAINER_HEADER_ELEMENT_COUNT = 1; 88 private static final int LOCK_UNLOCK_BUTTON_COUNT = 1; 89 private static final int PS_SETTINGS_BUTTON_COUNT_VISIBLE = 1; 90 private static final int PS_SETTINGS_BUTTON_COUNT_INVISIBLE = 0; 91 private static final int PS_TRANSITION_IMAGE_COUNT = 1; 92 private static final int NUM_APP_COLS = 4; 93 private static final int NUM_PRIVATE_SPACE_APPS = 50; 94 private static final int ALL_APPS_HEIGHT = 10; 95 private static final int ALL_APPS_CELL_HEIGHT = 1; 96 private static final int PS_HEADER_HEIGHT = 1; 97 private static final int BIGGER_PS_HEADER_HEIGHT = 2; 98 private static final int SCROLL_NO_WHERE = -1; 99 private static final float HEADER_PROTECTION_HEIGHT = 1F; 100 101 private Context mContext; 102 private RelativeLayout mPsHeaderLayout; 103 private AlphabeticalAppsList<?> mAlphabeticalAppsList; 104 private PrivateProfileManager mPrivateProfileManager; 105 @Mock 106 private ActivityAllAppsContainerView mAllApps; 107 @Mock 108 private AllAppsStore<?> mAllAppsStore; 109 @Mock 110 private UserCache mUserCache; 111 @Mock 112 private UserManager mUserManager; 113 @Mock 114 private StatsLogManager mStatsLogManager; 115 116 @Before setUp()117 public void setUp() { 118 MockitoAnnotations.initMocks(this); 119 mContext = new ActivityContextWrapper(getApplicationContext()); 120 when(mAllApps.getContext()).thenReturn(mContext); 121 when(mUserCache.getUserInfo(PRIVATE_HANDLE)).thenReturn(PRIVATE_ICON_INFO); 122 when(mUserCache.getUserProfiles()) 123 .thenReturn(Arrays.asList(MAIN_HANDLE, PRIVATE_HANDLE)); 124 when(mUserCache.getUserInfo(Process.myUserHandle())).thenReturn(MAIN_ICON_INFO); 125 mPrivateProfileManager = new PrivateProfileManager(mUserManager, 126 mAllApps, mStatsLogManager, mUserCache); 127 mPsHeaderLayout = (RelativeLayout) LayoutInflater.from(mContext).inflate( 128 R.layout.private_space_header, null); 129 } 130 131 @Test privateProfileDisabled_psHeaderContainsLockedView()132 public void privateProfileDisabled_psHeaderContainsLockedView() throws Exception { 133 Bitmap unlockButton = getBitmap(mContext.getDrawable(R.drawable.ic_lock)); 134 PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager); 135 when(privateProfileManager.getCurrentState()).thenReturn(STATE_DISABLED); 136 privateProfileManager.bindPrivateSpaceHeaderViewElements(mPsHeaderLayout); 137 awaitTasksCompleted(); 138 139 int totalContainerHeaderView = 0; 140 int totalLockUnlockButtonView = 0; 141 for (int i = 0; i < mPsHeaderLayout.getChildCount(); i++) { 142 View view = mPsHeaderLayout.getChildAt(i); 143 if (view.getId() == R.id.ps_container_header) { 144 totalContainerHeaderView += 1; 145 assertEquals(View.VISIBLE, view.getVisibility()); 146 } else if (view.getId() == R.id.settingsAndLockGroup) { 147 ImageView lockIcon = view.findViewById(R.id.lock_icon); 148 assertTrue(getBitmap(lockIcon.getDrawable()).sameAs(unlockButton)); 149 assertEquals(View.VISIBLE, lockIcon.getVisibility()); 150 151 // Verify textView shouldn't be showing when disabled. 152 TextView lockText = view.findViewById(R.id.lock_text); 153 assertEquals(View.GONE, lockText.getVisibility()); 154 totalLockUnlockButtonView += 1; 155 } else { 156 assertEquals(View.GONE, view.getVisibility()); 157 } 158 } 159 160 assertEquals(CONTAINER_HEADER_ELEMENT_COUNT, totalContainerHeaderView); 161 assertEquals(LOCK_UNLOCK_BUTTON_COUNT, totalLockUnlockButtonView); 162 } 163 164 @Test privateProfileEnabled_psHeaderContainsUnlockedView()165 public void privateProfileEnabled_psHeaderContainsUnlockedView() throws Exception { 166 Bitmap lockImage = getBitmap(mContext.getDrawable(R.drawable.ic_lock)); 167 Bitmap settingsImage = getBitmap(mContext.getDrawable(R.drawable.ic_ps_settings)); 168 PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager); 169 when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED); 170 when(privateProfileManager.isPrivateSpaceSettingsAvailable()).thenReturn(true); 171 privateProfileManager.bindPrivateSpaceHeaderViewElements(mPsHeaderLayout); 172 awaitTasksCompleted(); 173 174 int totalContainerHeaderView = 0; 175 int totalLockUnlockButtonView = 0; 176 int totalSettingsImageView = 0; 177 for (int i = 0; i < mPsHeaderLayout.getChildCount(); i++) { 178 View view = mPsHeaderLayout.getChildAt(i); 179 if (view.getId() == R.id.ps_container_header) { 180 totalContainerHeaderView += 1; 181 assertEquals(View.VISIBLE, view.getVisibility()); 182 } else if (view.getId() == R.id.settingsAndLockGroup) { 183 // Look for settings button. 184 ImageButton settingsButton = view.findViewById(R.id.ps_settings_button); 185 assertEquals(View.VISIBLE, settingsButton.getVisibility()); 186 totalSettingsImageView += 1; 187 assertTrue(getBitmap(settingsButton.getDrawable()).sameAs(settingsImage)); 188 189 // Look for lock_icon and lock_text. 190 ImageView lockIcon = view.findViewById(R.id.lock_icon); 191 assertTrue(getBitmap(lockIcon.getDrawable()).sameAs(lockImage)); 192 assertEquals(View.VISIBLE, lockIcon.getVisibility()); 193 TextView lockText = view.findViewById(R.id.lock_text); 194 assertEquals(View.VISIBLE, lockText.getVisibility()); 195 totalLockUnlockButtonView += 1; 196 } else { 197 assertEquals(View.GONE, view.getVisibility()); 198 } 199 } 200 201 assertEquals(CONTAINER_HEADER_ELEMENT_COUNT, totalContainerHeaderView); 202 assertEquals(LOCK_UNLOCK_BUTTON_COUNT, totalLockUnlockButtonView); 203 assertEquals(PS_SETTINGS_BUTTON_COUNT_VISIBLE, totalSettingsImageView); 204 } 205 206 @Test privateProfileEnabledAndNoSettingsIntent_psHeaderContainsUnlockedView()207 public void privateProfileEnabledAndNoSettingsIntent_psHeaderContainsUnlockedView() 208 throws Exception { 209 Bitmap lockImage = getBitmap(mContext.getDrawable(R.drawable.ic_lock)); 210 PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager); 211 when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED); 212 when(privateProfileManager.isPrivateSpaceSettingsAvailable()).thenReturn(false); 213 privateProfileManager.bindPrivateSpaceHeaderViewElements(mPsHeaderLayout); 214 awaitTasksCompleted(); 215 216 int totalContainerHeaderView = 0; 217 int totalLockUnlockButtonView = 0; 218 int totalSettingsImageView = 0; 219 for (int i = 0; i < mPsHeaderLayout.getChildCount(); i++) { 220 View view = mPsHeaderLayout.getChildAt(i); 221 if (view.getId() == R.id.ps_container_header) { 222 totalContainerHeaderView += 1; 223 assertEquals(View.VISIBLE, view.getVisibility()); 224 } else if (view.getId() == R.id.settingsAndLockGroup) { 225 // Ensure there is no settings button. 226 ImageButton settingsImage = view.findViewById(R.id.ps_settings_button); 227 assertEquals(View.GONE, settingsImage.getVisibility()); 228 229 // Check lock icon and lock text is there. 230 ImageView lockIcon = view.findViewById(R.id.lock_icon); 231 assertTrue(getBitmap(lockIcon.getDrawable()).sameAs(lockImage)); 232 assertEquals(View.VISIBLE, lockIcon.getVisibility()); 233 TextView lockText = view.findViewById(R.id.lock_text); 234 assertEquals(View.VISIBLE, lockText.getVisibility()); 235 totalLockUnlockButtonView += 1; 236 } else { 237 assertEquals(View.GONE, view.getVisibility()); 238 } 239 } 240 241 assertEquals(CONTAINER_HEADER_ELEMENT_COUNT, totalContainerHeaderView); 242 assertEquals(LOCK_UNLOCK_BUTTON_COUNT, totalLockUnlockButtonView); 243 assertEquals(PS_SETTINGS_BUTTON_COUNT_INVISIBLE, totalSettingsImageView); 244 } 245 246 @Test privateProfileTransitioning_psHeaderContainsTransitionView()247 public void privateProfileTransitioning_psHeaderContainsTransitionView() throws Exception { 248 Bitmap transitionImage = getBitmap(mContext.getDrawable(R.drawable.bg_ps_transition_image)); 249 PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager); 250 when(privateProfileManager.getCurrentState()).thenReturn(STATE_TRANSITION); 251 privateProfileManager.bindPrivateSpaceHeaderViewElements(mPsHeaderLayout); 252 awaitTasksCompleted(); 253 254 int totalContainerHeaderView = 0; 255 int totalLockUnlockButtonView = 0; 256 for (int i = 0; i < mPsHeaderLayout.getChildCount(); i++) { 257 View view = mPsHeaderLayout.getChildAt(i); 258 if (view.getId() == R.id.ps_container_header) { 259 totalContainerHeaderView += 1; 260 assertEquals(View.VISIBLE, view.getVisibility()); 261 } else if (view.getId() == R.id.ps_transition_image 262 && view instanceof ImageView imageView) { 263 totalLockUnlockButtonView += 1; 264 assertEquals(View.VISIBLE, view.getVisibility()); 265 assertTrue(getBitmap(imageView.getDrawable()).sameAs(transitionImage)); 266 } else if (view.getId() == R.id.settingsAndLockGroup) { 267 LinearLayout lockUnlockButton = view.findViewById(R.id.ps_lock_unlock_button); 268 assertEquals(View.GONE, lockUnlockButton.getVisibility()); 269 } else { 270 assertEquals(View.GONE, view.getVisibility()); 271 } 272 } 273 274 assertEquals(CONTAINER_HEADER_ELEMENT_COUNT, totalContainerHeaderView); 275 assertEquals(PS_TRANSITION_IMAGE_COUNT, totalLockUnlockButtonView); 276 } 277 278 @Test scrollForViewToBeVisibleInContainer_withHeader()279 public void scrollForViewToBeVisibleInContainer_withHeader() { 280 when(mAllAppsStore.getApps()).thenReturn(createAppInfoList()); 281 PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager); 282 when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED); 283 doReturn(splitIntoUserInstalledAndSystemApps()).when(privateProfileManager) 284 .splitIntoUserInstalledAndSystemApps(any()); 285 doReturn(0).when(privateProfileManager).addPrivateSpaceHeader(any()); 286 doAnswer(answer(this::addPrivateSpaceHeader)).when(privateProfileManager) 287 .addPrivateSpaceHeader(any()); 288 doNothing().when(privateProfileManager).addPrivateSpaceInstallAppButton(any()); 289 doReturn(0).when(privateProfileManager).addSystemAppsDivider(any()); 290 when(mAllApps.getHeight()).thenReturn(ALL_APPS_HEIGHT); 291 when(mAllApps.getHeaderProtectionHeight()).thenReturn(HEADER_PROTECTION_HEIGHT); 292 when(mAllApps.isUsingTabs()).thenReturn(true); 293 mAlphabeticalAppsList = new AlphabeticalAppsList<>(mContext, mAllAppsStore, 294 null, privateProfileManager); 295 mAlphabeticalAppsList.setNumAppsPerRowAllApps(NUM_APP_COLS); 296 mAlphabeticalAppsList.updateItemFilter(info -> info != null 297 && info.user.equals(MAIN_HANDLE)); 298 299 int rows = (int) (ALL_APPS_HEIGHT - PS_HEADER_HEIGHT - HEADER_PROTECTION_HEIGHT); 300 int position = rows * NUM_APP_COLS - (NUM_APP_COLS-1) + 1; 301 302 // The number of adapterItems should be the private space apps + one main app + header. 303 assertEquals(NUM_PRIVATE_SPACE_APPS + 1 + 1, 304 mAlphabeticalAppsList.getAdapterItems().size()); 305 assertEquals(position, 306 privateProfileManager.scrollForHeaderToBeVisibleInContainer( 307 new AllAppsRecyclerView(mContext), 308 mAlphabeticalAppsList.getAdapterItems(), 309 PS_HEADER_HEIGHT, 310 ALL_APPS_CELL_HEIGHT)); 311 } 312 313 @Test scrollForViewToBeVisibleInContainer_withHeaderNoTabs()314 public void scrollForViewToBeVisibleInContainer_withHeaderNoTabs() { 315 when(mAllAppsStore.getApps()).thenReturn(createAppInfoList()); 316 PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager); 317 when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED); 318 doReturn(splitIntoUserInstalledAndSystemApps()).when(privateProfileManager) 319 .splitIntoUserInstalledAndSystemApps(any()); 320 doReturn(0).when(privateProfileManager).addPrivateSpaceHeader(any()); 321 doAnswer(answer(this::addPrivateSpaceHeader)).when(privateProfileManager) 322 .addPrivateSpaceHeader(any()); 323 doNothing().when(privateProfileManager).addPrivateSpaceInstallAppButton(any()); 324 doReturn(0).when(privateProfileManager).addSystemAppsDivider(any()); 325 when(mAllApps.getHeight()).thenReturn(ALL_APPS_HEIGHT); 326 when(mAllApps.getHeaderProtectionHeight()).thenReturn(HEADER_PROTECTION_HEIGHT); 327 when(mAllApps.isUsingTabs()).thenReturn(false); 328 mAlphabeticalAppsList = new AlphabeticalAppsList<>(mContext, mAllAppsStore, 329 null, privateProfileManager); 330 mAlphabeticalAppsList.setNumAppsPerRowAllApps(NUM_APP_COLS); 331 mAlphabeticalAppsList.updateItemFilter(info -> info != null 332 && info.user.equals(MAIN_HANDLE)); 333 334 int rows = (int) (ALL_APPS_HEIGHT - PS_HEADER_HEIGHT - HEADER_PROTECTION_HEIGHT) - 1; 335 int position = rows * NUM_APP_COLS - (NUM_APP_COLS-1) + 1; 336 337 // The number of adapterItems should be the private space apps + one main app + header. 338 assertEquals(NUM_PRIVATE_SPACE_APPS + 1 + 1, 339 mAlphabeticalAppsList.getAdapterItems().size()); 340 assertEquals(position, 341 privateProfileManager.scrollForHeaderToBeVisibleInContainer( 342 new AllAppsRecyclerView(mContext), 343 mAlphabeticalAppsList.getAdapterItems(), 344 PS_HEADER_HEIGHT, 345 ALL_APPS_CELL_HEIGHT)); 346 } 347 348 @Test scrollForViewToBeVisibleInContainer_withHeaderAndLessAppRowSpace()349 public void scrollForViewToBeVisibleInContainer_withHeaderAndLessAppRowSpace() { 350 when(mAllAppsStore.getApps()).thenReturn(createAppInfoList()); 351 PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager); 352 when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED); 353 doReturn(splitIntoUserInstalledAndSystemApps()).when(privateProfileManager) 354 .splitIntoUserInstalledAndSystemApps(any()); 355 doReturn(0).when(privateProfileManager).addPrivateSpaceHeader(any()); 356 doAnswer(answer(this::addPrivateSpaceHeader)).when(privateProfileManager) 357 .addPrivateSpaceHeader(any()); 358 doNothing().when(privateProfileManager).addPrivateSpaceInstallAppButton(any()); 359 doReturn(0).when(privateProfileManager).addSystemAppsDivider(any()); 360 when(mAllApps.getHeight()).thenReturn(ALL_APPS_HEIGHT); 361 when(mAllApps.isUsingTabs()).thenReturn(true); 362 when(mAllApps.getHeaderProtectionHeight()).thenReturn(HEADER_PROTECTION_HEIGHT); 363 mAlphabeticalAppsList = new AlphabeticalAppsList<>(mContext, mAllAppsStore, 364 null, privateProfileManager); 365 mAlphabeticalAppsList.setNumAppsPerRowAllApps(NUM_APP_COLS); 366 mAlphabeticalAppsList.updateItemFilter(info -> info != null 367 && info.user.equals(MAIN_HANDLE)); 368 369 int rows = (int) (ALL_APPS_HEIGHT - BIGGER_PS_HEADER_HEIGHT - HEADER_PROTECTION_HEIGHT); 370 int position = rows * NUM_APP_COLS - (NUM_APP_COLS-1) + 1; 371 372 // The number of adapterItems should be the private space apps + one main app + header. 373 assertEquals(NUM_PRIVATE_SPACE_APPS + 1 + 1, 374 mAlphabeticalAppsList.getAdapterItems().size()); 375 assertEquals(position, 376 privateProfileManager.scrollForHeaderToBeVisibleInContainer( 377 new AllAppsRecyclerView(mContext), 378 mAlphabeticalAppsList.getAdapterItems(), 379 BIGGER_PS_HEADER_HEIGHT, 380 ALL_APPS_CELL_HEIGHT)); 381 } 382 383 @Test scrollForViewToBeVisibleInContainer_withNoHeader()384 public void scrollForViewToBeVisibleInContainer_withNoHeader() { 385 when(mAllAppsStore.getApps()).thenReturn(createAppInfoList()); 386 PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager); 387 when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED); 388 doReturn(splitIntoUserInstalledAndSystemApps()).when(privateProfileManager) 389 .splitIntoUserInstalledAndSystemApps(any()); 390 doReturn(0).when(privateProfileManager).addPrivateSpaceHeader(any()); 391 doNothing().when(privateProfileManager).addPrivateSpaceInstallAppButton(any()); 392 doReturn(0).when(privateProfileManager).addSystemAppsDivider(any()); 393 when(mAllApps.getHeight()).thenReturn(ALL_APPS_HEIGHT); 394 when(mAllApps.getHeaderProtectionHeight()).thenReturn(HEADER_PROTECTION_HEIGHT); 395 mAlphabeticalAppsList = new AlphabeticalAppsList<>(mContext, mAllAppsStore, 396 null, privateProfileManager); 397 mAlphabeticalAppsList.setNumAppsPerRowAllApps(NUM_APP_COLS); 398 mAlphabeticalAppsList.updateItemFilter(info -> info != null 399 && info.user.equals(MAIN_HANDLE)); 400 401 // The number of adapterItems should be the private space apps + one main app. 402 assertEquals(NUM_PRIVATE_SPACE_APPS + 1, 403 mAlphabeticalAppsList.getAdapterItems().size()); 404 assertEquals(SCROLL_NO_WHERE, privateProfileManager.scrollForHeaderToBeVisibleInContainer( 405 new AllAppsRecyclerView(mContext), 406 mAlphabeticalAppsList.getAdapterItems(), 407 BIGGER_PS_HEADER_HEIGHT, 408 ALL_APPS_CELL_HEIGHT)); 409 } 410 getBitmap(Drawable drawable)411 private Bitmap getBitmap(Drawable drawable) { 412 Bitmap result; 413 if (drawable instanceof BitmapDrawable) { 414 result = ((BitmapDrawable) drawable).getBitmap(); 415 } else { 416 int width = drawable.getIntrinsicWidth(); 417 int height = drawable.getIntrinsicHeight(); 418 // Some drawables have no intrinsic width - e.g. solid colours. 419 if (width <= 0) { 420 width = 1; 421 } 422 if (height <= 0) { 423 height = 1; 424 } 425 426 result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 427 Canvas canvas = new Canvas(result); 428 drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); 429 drawable.draw(canvas); 430 } 431 return result; 432 } 433 awaitTasksCompleted()434 private static void awaitTasksCompleted() throws Exception { 435 UI_HELPER_EXECUTOR.submit(() -> null).get(); 436 } 437 addPrivateSpaceHeader(List<BaseAllAppsAdapter.AdapterItem> adapterItemList)438 private int addPrivateSpaceHeader(List<BaseAllAppsAdapter.AdapterItem> adapterItemList) { 439 BaseAllAppsAdapter.AdapterItem privateSpaceHeader = 440 new BaseAllAppsAdapter.AdapterItem(VIEW_TYPE_PRIVATE_SPACE_HEADER); 441 adapterItemList.add(privateSpaceHeader); 442 return adapterItemList.size(); 443 } 444 createAppInfoList()445 private AppInfo[] createAppInfoList() { 446 List<AppInfo> appInfos = new ArrayList<>(); 447 ComponentName gmailComponentName = new ComponentName(mContext, 448 "com.android.launcher3.tests.Activity" + "Gmail"); 449 AppInfo gmailAppInfo = new 450 AppInfo(gmailComponentName, "Gmail", MAIN_HANDLE, new Intent()); 451 appInfos.add(gmailAppInfo); 452 ComponentName privateCameraComponentName = new ComponentName( 453 CAMERA_PACKAGE_NAME, "CameraActivity"); 454 for (int i = 0; i < NUM_PRIVATE_SPACE_APPS; i++) { 455 AppInfo privateCameraAppInfo = new AppInfo(privateCameraComponentName, 456 "Private Camera " + i, PRIVATE_HANDLE, new Intent()); 457 appInfos.add(privateCameraAppInfo); 458 } 459 return appInfos.toArray(AppInfo[]::new); 460 } 461 splitIntoUserInstalledAndSystemApps()462 private Predicate<AppInfo> splitIntoUserInstalledAndSystemApps() { 463 return iteminfo -> iteminfo.componentName == null 464 || !iteminfo.componentName.getPackageName() 465 .equals(CAMERA_PACKAGE_NAME); 466 } 467 } 468