Move tests to multivalent

Test: SysUI studio
Test: atest NexusLauncherRoboTests
Flag: EXEMPT test migration
Change-Id: Idd9e52f281d955e87f6db638ebfd8218a4dcb77f
This commit is contained in:
Sihua Ma
2025-01-15 23:38:30 +00:00
parent f7f4c3c7ac
commit 8fc266d063
15 changed files with 59 additions and 33 deletions
@@ -0,0 +1,469 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.launcher3.allapps;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_PRIVATE_SPACE_HEADER;
import static com.android.launcher3.allapps.UserProfileManager.STATE_DISABLED;
import static com.android.launcher3.allapps.UserProfileManager.STATE_ENABLED;
import static com.android.launcher3.allapps.UserProfileManager.STATE_TRANSITION;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.AdditionalAnswers.answer;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.android.launcher3.R;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.pm.UserCache;
import com.android.launcher3.util.ActivityContextWrapper;
import com.android.launcher3.util.UserIconInfo;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class PrivateSpaceHeaderViewTest {
private static final UserHandle MAIN_HANDLE = Process.myUserHandle();
private static final UserHandle PRIVATE_HANDLE = new UserHandle(11);
private static final UserIconInfo MAIN_ICON_INFO =
new UserIconInfo(MAIN_HANDLE, UserIconInfo.TYPE_MAIN);
private static final UserIconInfo PRIVATE_ICON_INFO =
new UserIconInfo(PRIVATE_HANDLE, UserIconInfo.TYPE_PRIVATE);
private static final String CAMERA_PACKAGE_NAME = "com.android.launcher3.tests.camera";
private static final int CONTAINER_HEADER_ELEMENT_COUNT = 1;
private static final int LOCK_UNLOCK_BUTTON_COUNT = 1;
private static final int MAIN_USER_APP_COUNT = 1;
private static final int VIEW_AT_END_OF_APP_LIST = 1;
private static final int PS_SETTINGS_BUTTON_COUNT_VISIBLE = 1;
private static final int PS_SETTINGS_BUTTON_COUNT_INVISIBLE = 0;
private static final int PS_TRANSITION_IMAGE_COUNT = 1;
private static final int NUM_APP_COLS = 4;
private static final int NUM_PRIVATE_SPACE_APPS = 50;
private static final int ALL_APPS_HEIGHT = 10;
private static final int ALL_APPS_CELL_HEIGHT = 1;
private static final int PS_HEADER_HEIGHT = 1;
private static final int BIGGER_PS_HEADER_HEIGHT = 2;
private static final int SCROLL_NO_WHERE = -1;
private static final float HEADER_PROTECTION_HEIGHT = 1F;
private Context mContext;
private RelativeLayout mPsHeaderLayout;
private AlphabeticalAppsList<?> mAlphabeticalAppsList;
private PrivateProfileManager mPrivateProfileManager;
@Mock
private ActivityAllAppsContainerView mAllApps;
@Mock
private AllAppsStore<?> mAllAppsStore;
@Mock
private UserCache mUserCache;
@Mock
private UserManager mUserManager;
@Mock
private StatsLogManager mStatsLogManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = new ActivityContextWrapper(getApplicationContext(),
R.style.DynamicColorsBaseLauncherTheme);
when(mAllApps.getContext()).thenReturn(mContext);
when(mUserCache.getUserInfo(PRIVATE_HANDLE)).thenReturn(PRIVATE_ICON_INFO);
when(mUserCache.getUserProfiles())
.thenReturn(Arrays.asList(MAIN_HANDLE, PRIVATE_HANDLE));
when(mUserCache.getUserInfo(Process.myUserHandle())).thenReturn(MAIN_ICON_INFO);
mPrivateProfileManager = new PrivateProfileManager(mUserManager,
mAllApps, mStatsLogManager, mUserCache);
mPsHeaderLayout = (RelativeLayout) LayoutInflater.from(mContext).inflate(
R.layout.private_space_header, null);
}
@Test
public void privateProfileDisabled_psHeaderContainsLockedView() throws Exception {
Bitmap unlockButton = getBitmap(mContext.getDrawable(R.drawable.ic_lock));
PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
when(privateProfileManager.getCurrentState()).thenReturn(STATE_DISABLED);
privateProfileManager.bindPrivateSpaceHeaderViewElements(mPsHeaderLayout);
awaitTasksCompleted();
int totalContainerHeaderView = 0;
int totalLockUnlockButtonView = 0;
for (int i = 0; i < mPsHeaderLayout.getChildCount(); i++) {
View view = mPsHeaderLayout.getChildAt(i);
if (view.getId() == R.id.ps_container_header) {
totalContainerHeaderView += 1;
assertEquals(View.VISIBLE, view.getVisibility());
} else if (view.getId() == R.id.settingsAndLockGroup) {
ImageView lockIcon = view.findViewById(R.id.lock_icon);
assertTrue(getBitmap(lockIcon.getDrawable()).sameAs(unlockButton));
assertEquals(View.VISIBLE, lockIcon.getVisibility());
// Verify textView shouldn't be showing when disabled.
TextView lockText = view.findViewById(R.id.lock_text);
assertEquals(View.GONE, lockText.getVisibility());
totalLockUnlockButtonView += 1;
} else {
assertEquals(View.GONE, view.getVisibility());
}
}
assertEquals(CONTAINER_HEADER_ELEMENT_COUNT, totalContainerHeaderView);
assertEquals(LOCK_UNLOCK_BUTTON_COUNT, totalLockUnlockButtonView);
}
@Test
public void privateProfileEnabled_psHeaderContainsUnlockedView() throws Exception {
Bitmap lockImage = getBitmap(mContext.getDrawable(R.drawable.ic_lock));
Bitmap settingsImage = getBitmap(mContext.getDrawable(R.drawable.ic_ps_settings));
PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
when(privateProfileManager.isPrivateSpaceSettingsAvailable()).thenReturn(true);
privateProfileManager.bindPrivateSpaceHeaderViewElements(mPsHeaderLayout);
awaitTasksCompleted();
int totalContainerHeaderView = 0;
int totalLockUnlockButtonView = 0;
int totalSettingsImageView = 0;
for (int i = 0; i < mPsHeaderLayout.getChildCount(); i++) {
View view = mPsHeaderLayout.getChildAt(i);
if (view.getId() == R.id.ps_container_header) {
totalContainerHeaderView += 1;
assertEquals(View.VISIBLE, view.getVisibility());
} else if (view.getId() == R.id.settingsAndLockGroup) {
// Look for settings button.
ImageButton settingsButton = view.findViewById(R.id.ps_settings_button);
assertEquals(View.VISIBLE, settingsButton.getVisibility());
totalSettingsImageView += 1;
assertTrue(getBitmap(settingsButton.getDrawable()).sameAs(settingsImage));
// Look for lock_icon and lock_text.
ImageView lockIcon = view.findViewById(R.id.lock_icon);
assertTrue(getBitmap(lockIcon.getDrawable()).sameAs(lockImage));
assertEquals(View.VISIBLE, lockIcon.getVisibility());
TextView lockText = view.findViewById(R.id.lock_text);
assertEquals(View.VISIBLE, lockText.getVisibility());
totalLockUnlockButtonView += 1;
} else {
assertEquals(View.GONE, view.getVisibility());
}
}
assertEquals(CONTAINER_HEADER_ELEMENT_COUNT, totalContainerHeaderView);
assertEquals(LOCK_UNLOCK_BUTTON_COUNT, totalLockUnlockButtonView);
assertEquals(PS_SETTINGS_BUTTON_COUNT_VISIBLE, totalSettingsImageView);
}
@Test
public void privateProfileEnabledAndNoSettingsIntent_psHeaderContainsUnlockedView()
throws Exception {
Bitmap lockImage = getBitmap(mContext.getDrawable(R.drawable.ic_lock));
PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
when(privateProfileManager.isPrivateSpaceSettingsAvailable()).thenReturn(false);
privateProfileManager.bindPrivateSpaceHeaderViewElements(mPsHeaderLayout);
awaitTasksCompleted();
int totalContainerHeaderView = 0;
int totalLockUnlockButtonView = 0;
int totalSettingsImageView = 0;
for (int i = 0; i < mPsHeaderLayout.getChildCount(); i++) {
View view = mPsHeaderLayout.getChildAt(i);
if (view.getId() == R.id.ps_container_header) {
totalContainerHeaderView += 1;
assertEquals(View.VISIBLE, view.getVisibility());
} else if (view.getId() == R.id.settingsAndLockGroup) {
// Ensure there is no settings button.
ImageButton settingsImage = view.findViewById(R.id.ps_settings_button);
assertEquals(View.GONE, settingsImage.getVisibility());
// Check lock icon and lock text is there.
ImageView lockIcon = view.findViewById(R.id.lock_icon);
assertTrue(getBitmap(lockIcon.getDrawable()).sameAs(lockImage));
assertEquals(View.VISIBLE, lockIcon.getVisibility());
TextView lockText = view.findViewById(R.id.lock_text);
assertEquals(View.VISIBLE, lockText.getVisibility());
totalLockUnlockButtonView += 1;
} else {
assertEquals(View.GONE, view.getVisibility());
}
}
assertEquals(CONTAINER_HEADER_ELEMENT_COUNT, totalContainerHeaderView);
assertEquals(LOCK_UNLOCK_BUTTON_COUNT, totalLockUnlockButtonView);
assertEquals(PS_SETTINGS_BUTTON_COUNT_INVISIBLE, totalSettingsImageView);
}
@Test
public void privateProfileTransitioning_psHeaderContainsTransitionView() throws Exception {
Bitmap transitionImage = getBitmap(mContext.getDrawable(R.drawable.bg_ps_transition_image));
PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
when(privateProfileManager.getCurrentState()).thenReturn(STATE_TRANSITION);
privateProfileManager.bindPrivateSpaceHeaderViewElements(mPsHeaderLayout);
awaitTasksCompleted();
int totalContainerHeaderView = 0;
int totalLockUnlockButtonView = 0;
for (int i = 0; i < mPsHeaderLayout.getChildCount(); i++) {
View view = mPsHeaderLayout.getChildAt(i);
if (view.getId() == R.id.ps_container_header) {
totalContainerHeaderView += 1;
assertEquals(View.VISIBLE, view.getVisibility());
} else if (view.getId() == R.id.ps_transition_image
&& view instanceof ImageView imageView) {
totalLockUnlockButtonView += 1;
assertEquals(View.VISIBLE, view.getVisibility());
assertTrue(getBitmap(imageView.getDrawable()).sameAs(transitionImage));
} else if (view.getId() == R.id.settingsAndLockGroup) {
LinearLayout lockUnlockButton = view.findViewById(R.id.ps_lock_unlock_button);
assertEquals(View.GONE, lockUnlockButton.getVisibility());
} else {
assertEquals(View.GONE, view.getVisibility());
}
}
assertEquals(CONTAINER_HEADER_ELEMENT_COUNT, totalContainerHeaderView);
assertEquals(PS_TRANSITION_IMAGE_COUNT, totalLockUnlockButtonView);
}
@Test
public void scrollForViewToBeVisibleInContainer_withHeader() {
when(mAllAppsStore.getApps()).thenReturn(createAppInfoList());
PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
doReturn(splitIntoUserInstalledAndSystemApps()).when(privateProfileManager)
.splitIntoUserInstalledAndSystemApps(any());
doReturn(0).when(privateProfileManager).addPrivateSpaceHeader(any());
doAnswer(answer(this::addPrivateSpaceHeader)).when(privateProfileManager)
.addPrivateSpaceHeader(any());
doNothing().when(privateProfileManager).addPrivateSpaceInstallAppButton(any());
doReturn(0).when(privateProfileManager).addSystemAppsDivider(any());
when(mAllApps.getHeight()).thenReturn(ALL_APPS_HEIGHT);
when(mAllApps.getHeaderProtectionHeight()).thenReturn(HEADER_PROTECTION_HEIGHT);
when(mAllApps.isUsingTabs()).thenReturn(true);
mAlphabeticalAppsList = new AlphabeticalAppsList<>(mContext, mAllAppsStore,
null, privateProfileManager);
mAlphabeticalAppsList.setNumAppsPerRowAllApps(NUM_APP_COLS);
mAlphabeticalAppsList.updateItemFilter(info -> info != null
&& info.user.equals(MAIN_HANDLE));
int rows = (int) (ALL_APPS_HEIGHT - PS_HEADER_HEIGHT - HEADER_PROTECTION_HEIGHT);
int position = rows * NUM_APP_COLS - (NUM_APP_COLS - 1) + 1;
assertEquals(NUM_PRIVATE_SPACE_APPS + MAIN_USER_APP_COUNT
+ CONTAINER_HEADER_ELEMENT_COUNT + VIEW_AT_END_OF_APP_LIST,
mAlphabeticalAppsList.getAdapterItems().size());
assertEquals(position,
privateProfileManager.scrollForHeaderToBeVisibleInContainer(
new AllAppsRecyclerView(mContext),
mAlphabeticalAppsList.getAdapterItems(),
PS_HEADER_HEIGHT,
ALL_APPS_CELL_HEIGHT));
}
@Test
public void scrollForViewToBeVisibleInContainer_withHeaderNoTabs() {
when(mAllAppsStore.getApps()).thenReturn(createAppInfoList());
PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
doReturn(splitIntoUserInstalledAndSystemApps()).when(privateProfileManager)
.splitIntoUserInstalledAndSystemApps(any());
doReturn(0).when(privateProfileManager).addPrivateSpaceHeader(any());
doAnswer(answer(this::addPrivateSpaceHeader)).when(privateProfileManager)
.addPrivateSpaceHeader(any());
doNothing().when(privateProfileManager).addPrivateSpaceInstallAppButton(any());
doReturn(0).when(privateProfileManager).addSystemAppsDivider(any());
when(mAllApps.getHeight()).thenReturn(ALL_APPS_HEIGHT);
when(mAllApps.getHeaderProtectionHeight()).thenReturn(HEADER_PROTECTION_HEIGHT);
when(mAllApps.isUsingTabs()).thenReturn(false);
mAlphabeticalAppsList = new AlphabeticalAppsList<>(mContext, mAllAppsStore,
null, privateProfileManager);
mAlphabeticalAppsList.setNumAppsPerRowAllApps(NUM_APP_COLS);
mAlphabeticalAppsList.updateItemFilter(info -> info != null
&& info.user.equals(MAIN_HANDLE));
int rows = (int) (ALL_APPS_HEIGHT - PS_HEADER_HEIGHT - HEADER_PROTECTION_HEIGHT) - 1;
int position = rows * NUM_APP_COLS - (NUM_APP_COLS - 1) + 1;
assertEquals(NUM_PRIVATE_SPACE_APPS + MAIN_USER_APP_COUNT
+ CONTAINER_HEADER_ELEMENT_COUNT + VIEW_AT_END_OF_APP_LIST,
mAlphabeticalAppsList.getAdapterItems().size());
assertEquals(position,
privateProfileManager.scrollForHeaderToBeVisibleInContainer(
new AllAppsRecyclerView(mContext),
mAlphabeticalAppsList.getAdapterItems(),
PS_HEADER_HEIGHT,
ALL_APPS_CELL_HEIGHT));
}
@Test
public void scrollForViewToBeVisibleInContainer_withHeaderAndLessAppRowSpace() {
when(mAllAppsStore.getApps()).thenReturn(createAppInfoList());
PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
doReturn(splitIntoUserInstalledAndSystemApps()).when(privateProfileManager)
.splitIntoUserInstalledAndSystemApps(any());
doReturn(0).when(privateProfileManager).addPrivateSpaceHeader(any());
doAnswer(answer(this::addPrivateSpaceHeader)).when(privateProfileManager)
.addPrivateSpaceHeader(any());
doNothing().when(privateProfileManager).addPrivateSpaceInstallAppButton(any());
doReturn(0).when(privateProfileManager).addSystemAppsDivider(any());
when(mAllApps.getHeight()).thenReturn(ALL_APPS_HEIGHT);
when(mAllApps.isUsingTabs()).thenReturn(true);
when(mAllApps.getHeaderProtectionHeight()).thenReturn(HEADER_PROTECTION_HEIGHT);
mAlphabeticalAppsList = new AlphabeticalAppsList<>(mContext, mAllAppsStore,
null, privateProfileManager);
mAlphabeticalAppsList.setNumAppsPerRowAllApps(NUM_APP_COLS);
mAlphabeticalAppsList.updateItemFilter(info -> info != null
&& info.user.equals(MAIN_HANDLE));
int rows = (int) (ALL_APPS_HEIGHT - BIGGER_PS_HEADER_HEIGHT - HEADER_PROTECTION_HEIGHT);
int position = rows * NUM_APP_COLS - (NUM_APP_COLS - 1) + 1;
assertEquals(NUM_PRIVATE_SPACE_APPS + MAIN_USER_APP_COUNT
+ CONTAINER_HEADER_ELEMENT_COUNT + VIEW_AT_END_OF_APP_LIST,
mAlphabeticalAppsList.getAdapterItems().size());
assertEquals(position,
privateProfileManager.scrollForHeaderToBeVisibleInContainer(
new AllAppsRecyclerView(mContext),
mAlphabeticalAppsList.getAdapterItems(),
BIGGER_PS_HEADER_HEIGHT,
ALL_APPS_CELL_HEIGHT));
}
@Test
public void scrollForViewToBeVisibleInContainer_withNoHeader() {
when(mAllAppsStore.getApps()).thenReturn(createAppInfoList());
PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
doReturn(splitIntoUserInstalledAndSystemApps()).when(privateProfileManager)
.splitIntoUserInstalledAndSystemApps(any());
doReturn(0).when(privateProfileManager).addPrivateSpaceHeader(any());
doNothing().when(privateProfileManager).addPrivateSpaceInstallAppButton(any());
doReturn(0).when(privateProfileManager).addSystemAppsDivider(any());
when(mAllApps.getHeight()).thenReturn(ALL_APPS_HEIGHT);
when(mAllApps.getHeaderProtectionHeight()).thenReturn(HEADER_PROTECTION_HEIGHT);
mAlphabeticalAppsList = new AlphabeticalAppsList<>(mContext, mAllAppsStore,
null, privateProfileManager);
mAlphabeticalAppsList.setNumAppsPerRowAllApps(NUM_APP_COLS);
mAlphabeticalAppsList.updateItemFilter(info -> info != null
&& info.user.equals(MAIN_HANDLE));
assertEquals(NUM_PRIVATE_SPACE_APPS + MAIN_USER_APP_COUNT + VIEW_AT_END_OF_APP_LIST,
mAlphabeticalAppsList.getAdapterItems().size());
assertEquals(SCROLL_NO_WHERE, privateProfileManager.scrollForHeaderToBeVisibleInContainer(
new AllAppsRecyclerView(mContext),
mAlphabeticalAppsList.getAdapterItems(),
BIGGER_PS_HEADER_HEIGHT,
ALL_APPS_CELL_HEIGHT));
}
private Bitmap getBitmap(Drawable drawable) {
Bitmap result;
if (drawable instanceof BitmapDrawable) {
result = ((BitmapDrawable) drawable).getBitmap();
} else {
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
// Some drawables have no intrinsic width - e.g. solid colours.
if (width <= 0) {
width = 1;
}
if (height <= 0) {
height = 1;
}
result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(result);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
}
return result;
}
private static void awaitTasksCompleted() throws Exception {
UI_HELPER_EXECUTOR.submit(() -> null).get();
}
private int addPrivateSpaceHeader(List<BaseAllAppsAdapter.AdapterItem> adapterItemList) {
BaseAllAppsAdapter.AdapterItem privateSpaceHeader =
new BaseAllAppsAdapter.AdapterItem(VIEW_TYPE_PRIVATE_SPACE_HEADER);
adapterItemList.add(privateSpaceHeader);
return adapterItemList.size();
}
private AppInfo[] createAppInfoList() {
List<AppInfo> appInfos = new ArrayList<>();
ComponentName gmailComponentName = new ComponentName(mContext,
"com.android.launcher3.tests.Activity" + "Gmail");
AppInfo gmailAppInfo = new
AppInfo(gmailComponentName, "Gmail", MAIN_HANDLE, new Intent());
appInfos.add(gmailAppInfo);
ComponentName privateCameraComponentName = new ComponentName(
CAMERA_PACKAGE_NAME, "CameraActivity");
for (int i = 0; i < NUM_PRIVATE_SPACE_APPS; i++) {
AppInfo privateCameraAppInfo = new AppInfo(privateCameraComponentName,
"Private Camera " + i, PRIVATE_HANDLE, new Intent());
appInfos.add(privateCameraAppInfo);
}
return appInfos.toArray(AppInfo[]::new);
}
private Predicate<AppInfo> splitIntoUserInstalledAndSystemApps() {
return iteminfo -> iteminfo.componentName == null
|| !iteminfo.componentName.getPackageName()
.equals(CAMERA_PACKAGE_NAME);
}
}