Merge "Add Unit tests for System Shortcut." into main
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index fbbfea9..0af7e67 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -22,9 +22,7 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.Flags;
-import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
 import com.android.launcher3.SecondaryDropTarget;
 import com.android.launcher3.Utilities;
@@ -49,9 +47,10 @@
  * onClickListener that depends on the item that the shortcut services.
  *
  * Example system shortcuts, defined as inner classes, include Widgets and AppInfo.
- * @param <T>
+ *
+ * @param <T> extends {@link ActivityContext}
  */
-public abstract class SystemShortcut<T extends Context & ActivityContext> extends ItemInfo
+public abstract class SystemShortcut<T extends ActivityContext> extends ItemInfo
         implements View.OnClickListener {
 
     private final int mIconResId;
@@ -100,24 +99,25 @@
         return mAccessibilityActionId == action;
     }
 
-    public interface Factory<T extends Context & ActivityContext> {
+    public interface Factory<T extends ActivityContext> {
 
-        @Nullable SystemShortcut<T> getShortcut(T activity, ItemInfo itemInfo, View originalView);
+        @Nullable
+        SystemShortcut<T> getShortcut(T context, ItemInfo itemInfo, @NonNull View originalView);
     }
 
-    public static final Factory<Launcher> WIDGETS = (launcher, itemInfo, originalView) -> {
+    public static final Factory<ActivityContext> WIDGETS = (context, itemInfo, originalView) -> {
         if (itemInfo.getTargetComponent() == null) return null;
         final List<WidgetItem> widgets =
-                launcher.getPopupDataProvider().getWidgetsForPackageUser(new PackageUserKey(
+                context.getPopupDataProvider().getWidgetsForPackageUser(new PackageUserKey(
                         itemInfo.getTargetComponent().getPackageName(), itemInfo.user));
         if (widgets.isEmpty()) {
             return null;
         }
-        return new Widgets(launcher, itemInfo, originalView);
+        return new Widgets(context, itemInfo, originalView);
     };
 
-    public static class Widgets extends SystemShortcut<Launcher> {
-        public Widgets(Launcher target, ItemInfo itemInfo, View originalView) {
+    public static class Widgets<T extends ActivityContext> extends SystemShortcut<T> {
+        public Widgets(T target, ItemInfo itemInfo, @NonNull View originalView) {
             super(R.drawable.ic_widget, R.string.widget_button_text, target, itemInfo,
                     originalView);
         }
@@ -134,14 +134,14 @@
         }
     }
 
-    public static final Factory<BaseDraggingActivity> APP_INFO = AppInfo::new;
+    public static final Factory<ActivityContext> APP_INFO = AppInfo::new;
 
-    public static class AppInfo<T extends Context & ActivityContext> extends SystemShortcut<T> {
+    public static class AppInfo<T extends ActivityContext> extends SystemShortcut<T> {
 
         @Nullable
         private SplitAccessibilityInfo mSplitA11yInfo;
 
-        public AppInfo(T target, ItemInfo itemInfo, View originalView) {
+        public AppInfo(T target, ItemInfo itemInfo, @NonNull View originalView) {
             super(R.drawable.ic_info_no_shadow, R.string.app_info_drop_target_label, target,
                     itemInfo, originalView);
         }
@@ -180,7 +180,7 @@
         public void onClick(View view) {
             dismissTaskMenuView(mTarget);
             Rect sourceBounds = Utilities.getViewBounds(view);
-            new PackageManagerHelper(mTarget).startDetailsActivityForInfo(
+            new PackageManagerHelper(view.getContext()).startDetailsActivityForInfo(
                     mItemInfo, sourceBounds, ActivityOptions.makeBasic().toBundle());
             mTarget.getStatsLogManager().logger().withItemInfo(mItemInfo)
                     .log(LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP);
@@ -200,8 +200,11 @@
         }
     }
 
-    public static final Factory<Launcher> PRIVATE_PROFILE_INSTALL =
-            (launcher, itemInfo, originalView) -> {
+    public static final Factory<ActivityContext> PRIVATE_PROFILE_INSTALL =
+            (context, itemInfo, originalView) -> {
+                if (originalView == null) {
+                    return null;
+                }
                 if (itemInfo.getTargetComponent() == null
                         || !(itemInfo instanceof com.android.launcher3.model.data.AppInfo)
                         || !itemInfo.getContainerInfo().hasAllAppsContainer()
@@ -210,7 +213,7 @@
                 }
 
                 PrivateProfileManager privateProfileManager =
-                        launcher.getAppsView().getPrivateProfileManager();
+                        context.getAppsView().getPrivateProfileManager();
                 if (privateProfileManager == null || !privateProfileManager.isEnabled()) {
                     return null;
                 }
@@ -221,30 +224,28 @@
                 }
                 // Do not show shortcut if an app is already installed to the space
                 ComponentName targetComponent = itemInfo.getTargetComponent();
-                if (launcher.getAppsView()
-                                .getAppsStore()
-                                .getApp(new ComponentKey(targetComponent, privateProfileUser))
-                        != null) {
+                if (context.getAppsView().getAppsStore().getApp(
+                        new ComponentKey(targetComponent, privateProfileUser)) != null) {
                     return null;
                 }
 
                 // Do not show shortcut for settings
                 String[] packagesToSkip =
-                        launcher.getResources()
+                        originalView.getContext().getResources()
                                 .getStringArray(R.array.skip_private_profile_shortcut_packages);
                 if (Arrays.asList(packagesToSkip).contains(targetComponent.getPackageName())) {
                     return null;
                 }
 
-                return new InstallToPrivateProfile(
-                        launcher, itemInfo, originalView, privateProfileUser);
+                return new InstallToPrivateProfile<>(
+                        context, itemInfo, originalView, privateProfileUser);
             };
 
-    static class InstallToPrivateProfile extends SystemShortcut<Launcher> {
+    static class InstallToPrivateProfile<T extends ActivityContext> extends SystemShortcut<T> {
         UserHandle mSpaceUser;
 
-        InstallToPrivateProfile(
-                Launcher target, ItemInfo itemInfo, View originalView, UserHandle spaceUser) {
+        InstallToPrivateProfile(T target, ItemInfo itemInfo, @NonNull View originalView,
+                UserHandle spaceUser) {
             // TODO(b/302666597): update icon once available
             super(
                     R.drawable.ic_install_to_private,
@@ -271,8 +272,11 @@
         }
     }
 
-    public static final Factory<BaseDraggingActivity> INSTALL =
+    public static final Factory<ActivityContext> INSTALL =
             (activity, itemInfo, originalView) -> {
+                if (originalView == null) {
+                    return null;
+                }
                 boolean supportsWebUI = (itemInfo instanceof WorkspaceItemInfo)
                         && ((WorkspaceItemInfo) itemInfo).hasStatusFlag(
                         WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI);
@@ -280,18 +284,19 @@
                 if (itemInfo instanceof com.android.launcher3.model.data.AppInfo) {
                     com.android.launcher3.model.data.AppInfo
                             appInfo = (com.android.launcher3.model.data.AppInfo) itemInfo;
-                    isInstantApp = InstantAppResolver.newInstance(activity).isInstantApp(appInfo);
+                    isInstantApp = InstantAppResolver.newInstance(
+                            originalView.getContext()).isInstantApp(appInfo);
                 }
                 boolean enabled = supportsWebUI || isInstantApp;
                 if (!enabled) {
                     return null;
                 }
                 return new Install(activity, itemInfo, originalView);
-    };
+            };
 
-    public static class Install extends SystemShortcut<BaseDraggingActivity> {
+    public static class Install<T extends ActivityContext> extends SystemShortcut<T> {
 
-        public Install(BaseDraggingActivity target, ItemInfo itemInfo, View originalView) {
+        public Install(T target, ItemInfo itemInfo, @NonNull View originalView) {
             super(R.drawable.ic_install_no_shadow, R.string.install_drop_target_label,
                     target, itemInfo, originalView);
         }
@@ -306,16 +311,16 @@
         }
     }
 
-    public static final Factory<Launcher> DONT_SUGGEST_APP = (activity, itemInfo, originalView) -> {
-        if (!itemInfo.isPredictedItem()) {
-            return null;
-        }
-        return new DontSuggestApp(activity, itemInfo, originalView);
-    };
+    public static final Factory<ActivityContext> DONT_SUGGEST_APP =
+            (activity, itemInfo, originalView) -> {
+                if (!itemInfo.isPredictedItem()) {
+                    return null;
+                }
+                return new DontSuggestApp<>(activity, itemInfo, originalView);
+            };
 
-    private static class DontSuggestApp extends SystemShortcut<Launcher> {
-        DontSuggestApp(Launcher target, ItemInfo itemInfo,
-                View originalView) {
+    private static class DontSuggestApp<T extends ActivityContext> extends SystemShortcut<T> {
+        DontSuggestApp(T target, ItemInfo itemInfo, View originalView) {
             super(R.drawable.ic_block_no_shadow, R.string.dismiss_prediction_label, target,
                     itemInfo, originalView);
         }
@@ -329,36 +334,36 @@
         }
     }
 
-    public static final Factory<Launcher> UNINSTALL_APP = (activity, itemInfo, originalView) -> {
-        if (!Flags.enablePrivateSpace()) {
-            return null;
-        }
-        if (!UserCache.getInstance(activity.getApplicationContext()).getUserInfo(
-                itemInfo.user).isPrivate()) {
-            // If app is not Private Space app.
-            return null;
-        }
-        ComponentName cn = SecondaryDropTarget.getUninstallTarget(activity.getApplicationContext(),
-                itemInfo);
-        if (cn == null) {
-            // If component name is null, don't show uninstall shortcut.
-            // System apps will have component name as null.
-            return null;
-        }
-        return new UninstallApp(activity, itemInfo, originalView, cn);
-    };
+    public static final Factory<ActivityContext> UNINSTALL_APP =
+            (activityContext, itemInfo, originalView) -> {
+                if (originalView == null) {
+                    return null;
+                }
+                if (!Flags.enablePrivateSpace()) {
+                    return null;
+                }
+                if (!UserCache.INSTANCE.get(originalView.getContext()).getUserInfo(
+                        itemInfo.user).isPrivate()) {
+                    // If app is not Private Space app.
+                    return null;
+                }
+                ComponentName cn = SecondaryDropTarget.getUninstallTarget(originalView.getContext(),
+                        itemInfo);
+                if (cn == null) {
+                    // If component name is null, don't show uninstall shortcut.
+                    // System apps will have component name as null.
+                    return null;
+                }
+                return new UninstallApp(activityContext, itemInfo, originalView, cn);
+            };
 
-    private static class UninstallApp extends SystemShortcut<Launcher> {
-        private static final String TAG = "UninstallApp";
-        Context mContext;
-        @NonNull
-        ComponentName mComponentName;
+    private static class UninstallApp<T extends ActivityContext> extends SystemShortcut<T> {
+        @NonNull ComponentName mComponentName;
 
-        UninstallApp(Launcher target, ItemInfo itemInfo, View originalView,
+        UninstallApp(T target, ItemInfo itemInfo, @NonNull View originalView,
                 @NonNull ComponentName cn) {
             super(R.drawable.ic_uninstall_no_shadow, R.string.uninstall_drop_target_label, target,
                     itemInfo, originalView);
-            mContext = target.getApplicationContext();
             mComponentName = cn;
 
         }
@@ -366,7 +371,7 @@
         @Override
         public void onClick(View view) {
             dismissTaskMenuView(mTarget);
-            SecondaryDropTarget.performUninstall(mContext, mComponentName, mItemInfo);
+            SecondaryDropTarget.performUninstall(view.getContext(), mComponentName, mItemInfo);
             mTarget.getStatsLogManager()
                     .logger()
                     .withItemInfo(mItemInfo)
@@ -374,8 +379,8 @@
         }
     }
 
-    public static <T extends Context & ActivityContext> void dismissTaskMenuView(T activity) {
+    public static <T extends ActivityContext> void dismissTaskMenuView(T activity) {
         AbstractFloatingView.closeOpenViews(activity, true,
-            AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
+                AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
     }
 }
diff --git a/tests/multivalentTests/src/com/android/launcher3/util/TestSandboxModelContextWrapper.java b/tests/multivalentTests/src/com/android/launcher3/util/TestSandboxModelContextWrapper.java
new file mode 100644
index 0000000..3f37563
--- /dev/null
+++ b/tests/multivalentTests/src/com/android/launcher3/util/TestSandboxModelContextWrapper.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2024 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.util;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static com.android.launcher3.util.MainThreadInitializedObject.SandboxContext;
+
+import android.content.ContextWrapper;
+
+import androidx.annotation.Nullable;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
+import com.android.launcher3.allapps.AllAppsStore;
+import com.android.launcher3.allapps.AlphabeticalAppsList;
+import com.android.launcher3.model.BgDataModel;
+import com.android.launcher3.model.data.AppInfo;
+import com.android.launcher3.pm.UserCache;
+import com.android.launcher3.popup.PopupDataProvider;
+
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * {@link ContextWrapper} around {@link ActivityContextWrapper} with internal Launcher interface for
+ * testing.
+ *
+ * There are 2 constructors in this class. The base context can be {@link SandboxContext} or
+ * Instrumentation target context.
+ * Using {@link SandboxContext} as base context allows custom implementations for
+ * MainThreadInitializedObject providers.
+ */
+
+public class TestSandboxModelContextWrapper extends ActivityContextWrapper implements
+        BgDataModel.Callbacks {
+
+    protected AllAppsStore<ActivityContextWrapper> mAllAppsStore;
+    protected AlphabeticalAppsList<ActivityContextWrapper> mAppsList;
+
+    public final CountDownLatch mBindCompleted = new CountDownLatch(1);
+
+    protected ActivityAllAppsContainerView<ActivityContextWrapper> mAppsView;
+
+    private final PopupDataProvider mPopupDataProvider = new PopupDataProvider(i -> {});
+    protected final UserCache mUserCache;
+
+    public TestSandboxModelContextWrapper(SandboxContext base) {
+        super(base);
+        mUserCache = base.getObject(UserCache.INSTANCE);
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() ->
+                mAppsView = new ActivityAllAppsContainerView<>(this));
+        mAppsList = mAppsView.getPersonalAppList();
+        mAllAppsStore = mAppsView.getAppsStore();
+    }
+
+    public TestSandboxModelContextWrapper() {
+        super(getInstrumentation().getTargetContext());
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() ->
+                mAppsView = new ActivityAllAppsContainerView<>(this));
+        mUserCache = UserCache.getInstance(this);
+        mAppsList = mAppsView.getPersonalAppList();
+        mAllAppsStore = mAppsView.getAppsStore();
+    }
+    @Nullable
+    @Override
+    public PopupDataProvider getPopupDataProvider() {
+        return mPopupDataProvider;
+    }
+
+    @Override
+    public ActivityAllAppsContainerView<ActivityContextWrapper> getAppsView() {
+        return mAppsView;
+    }
+
+    @Override
+    public void bindAllApplications(AppInfo[] apps, int flags,
+            Map<PackageUserKey, Integer> packageUserKeytoUidMap) {
+        mAllAppsStore.setApps(apps, flags, packageUserKeytoUidMap);
+        mBindCompleted.countDown();
+    }
+}
diff --git a/tests/src/com/android/launcher3/popup/SystemShortcutTest.java b/tests/src/com/android/launcher3/popup/SystemShortcutTest.java
new file mode 100644
index 0000000..e459956
--- /dev/null
+++ b/tests/src/com/android/launcher3/popup/SystemShortcutTest.java
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2024 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.popup;
+
+import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static com.android.launcher3.Flags.FLAG_ENABLE_PRIVATE_SPACE;
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_ALL_APPS;
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
+import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
+import static com.android.launcher3.model.data.WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.LauncherActivityInfo;
+import android.content.pm.LauncherApps;
+import android.os.Process;
+import android.os.UserHandle;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.view.View;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.launcher3.allapps.PrivateProfileManager;
+import com.android.launcher3.model.data.AppInfo;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.pm.UserCache;
+import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext;
+import com.android.launcher3.util.TestSandboxModelContextWrapper;
+import com.android.launcher3.util.UserIconInfo;
+import com.android.launcher3.views.BaseDragLayer;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SystemShortcutTest {
+    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT);
+    private static final UserHandle PRIVATE_HANDLE = new UserHandle(11);
+    private static final UserHandle MAIN_HANDLE = Process.myUserHandle();
+    private View mView;
+    private ItemInfo mItemInfo;
+    private TestSandboxModelContextWrapper mTestContext;
+    private final SandboxModelContext mSandboxContext = new SandboxModelContext();
+    private PrivateProfileManager mPrivateProfileManager;
+    private PopupDataProvider mPopupDataProvider;
+    private AppInfo mAppInfo;
+    @Mock UserCache mUserCache;
+    @Mock BaseDragLayer mBaseDragLayer;
+    @Mock UserIconInfo mUserIconInfo;
+    @Mock LauncherActivityInfo mLauncherActivityInfo;
+    @Mock ApplicationInfo mApplicationInfo;
+    @Mock Intent mIntent;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mSandboxContext.putObject(UserCache.INSTANCE, mUserCache);
+        mTestContext = new TestSandboxModelContextWrapper(mSandboxContext);
+        mView = new View(mSandboxContext);
+        spyOn(mTestContext);
+        spyOn(mSandboxContext);
+        doReturn(mBaseDragLayer).when(mTestContext).getDragLayer();
+
+        mItemInfo = new ItemInfo();
+
+        LauncherApps mLauncherApps = mSandboxContext.spyService(LauncherApps.class);
+        doReturn(mLauncherActivityInfo).when(mLauncherApps).resolveActivity(any(), any());
+        when(mLauncherActivityInfo.getApplicationInfo()).thenReturn(mApplicationInfo);
+
+        when(mUserCache.getUserInfo(any())).thenReturn(mUserIconInfo);
+        when(mBaseDragLayer.getChildCount()).thenReturn(0);
+        mPrivateProfileManager = mTestContext.getAppsView().getPrivateProfileManager();
+        spyOn(mPrivateProfileManager);
+        when(mPrivateProfileManager.getProfileUser()).thenReturn(PRIVATE_HANDLE);
+
+        mPopupDataProvider = mTestContext.getPopupDataProvider();
+        spyOn(mPopupDataProvider);
+    }
+
+    @After
+    public void tearDown() {
+        mSandboxContext.onDestroy();
+    }
+
+    @Test
+    public void testWidgetsForNullComponentName() {
+        assertNull(mItemInfo.getTargetComponent());
+        SystemShortcut systemShortcut = SystemShortcut.WIDGETS
+                .getShortcut(mTestContext, mItemInfo, mView);
+        assertNull(systemShortcut);
+    }
+
+    @Test
+    public void testWidgetsForEmptyWidgetList() {
+        mAppInfo = new AppInfo();
+        mAppInfo.componentName = new ComponentName(mTestContext, getClass());
+        assertNotNull(mAppInfo.getTargetComponent());
+        doReturn(new ArrayList<>()).when(mPopupDataProvider).getWidgetsForPackageUser(any());
+        spyOn(mAppInfo);
+        SystemShortcut systemShortcut = SystemShortcut.WIDGETS
+                .getShortcut(mTestContext, mAppInfo, mView);
+        verify(mAppInfo, times(2)).getTargetComponent();
+        assertNull(systemShortcut);
+    }
+
+    @Test
+    public void testAppInfoShortcut() {
+        mAppInfo = new AppInfo();
+        mAppInfo.componentName = new ComponentName(mTestContext, getClass());
+        SystemShortcut systemShortcut = SystemShortcut.APP_INFO
+                .getShortcut(mTestContext, mAppInfo, mView);
+        assertNotNull(systemShortcut);
+    }
+
+
+    @Test
+    public void testDontSuggestAppForNonPredictedItem() {
+        assertFalse(mItemInfo.isPredictedItem());
+        SystemShortcut systemShortcut = SystemShortcut.DONT_SUGGEST_APP
+                .getShortcut(mTestContext, mItemInfo, mView);
+        assertNull(systemShortcut);
+    }
+
+    @Test
+    public void testDontSuggestAppForPredictedItem() {
+        mAppInfo = new AppInfo();
+        mAppInfo.componentName = new ComponentName(mTestContext, getClass());
+        mAppInfo.container = CONTAINER_HOTSEAT_PREDICTION;
+        assertTrue(mAppInfo.isPredictedItem());
+        SystemShortcut systemShortcut = SystemShortcut.DONT_SUGGEST_APP
+                .getShortcut(mTestContext, mAppInfo, mView);
+        assertNotNull(systemShortcut);
+        systemShortcut.onClick(mView);
+    }
+
+    @Test
+    public void testPrivateProfileInstallwithTargetComponentNull() {
+        assertNull(mItemInfo.getTargetComponent());
+        SystemShortcut systemShortcut = SystemShortcut.PRIVATE_PROFILE_INSTALL
+                .getShortcut(mTestContext, mItemInfo, mView);
+        assertNull(systemShortcut);
+    }
+
+    @Test
+    public void testPrivateProfileInstallNotAllAppsContainer() {
+        mAppInfo = new AppInfo();
+        mAppInfo.componentName = new ComponentName(mTestContext, getClass());
+        mAppInfo.container = CONTAINER_HOTSEAT_PREDICTION;
+
+        assertNotNull(mAppInfo.getTargetComponent());
+        assertFalse(mAppInfo.getContainerInfo().hasAllAppsContainer());
+
+        SystemShortcut systemShortcut = SystemShortcut.PRIVATE_PROFILE_INSTALL
+                .getShortcut(mTestContext, mAppInfo, mView);
+        assertNull(systemShortcut);
+    }
+
+    @Test
+    public void testPrivateProfileInstallNullPrivateProfileManager() {
+        mAppInfo = new AppInfo();
+        mAppInfo.componentName = new ComponentName(mTestContext, getClass());
+        mAppInfo.container = CONTAINER_ALL_APPS;
+        mPrivateProfileManager = null;
+
+        assertNotNull(mAppInfo.getTargetComponent());
+        assertTrue(mAppInfo.getContainerInfo().hasAllAppsContainer());
+        assertNull(mPrivateProfileManager);
+
+        SystemShortcut systemShortcut = SystemShortcut.PRIVATE_PROFILE_INSTALL
+                .getShortcut(mTestContext, mAppInfo, mView);
+        assertNull(systemShortcut);
+    }
+
+    @Test
+    public void testPrivateProfileInstallPrivateProfileManagerDisabled() {
+        mAppInfo = new AppInfo();
+        mAppInfo.componentName = new ComponentName(mTestContext, getClass());
+        mAppInfo.container = CONTAINER_ALL_APPS;
+
+        assertNotNull(mPrivateProfileManager);
+        assertNotNull(mAppInfo.getTargetComponent());
+        assertTrue(mAppInfo.getContainerInfo().hasAllAppsContainer());
+
+        when(mPrivateProfileManager.isEnabled()).thenReturn(false);
+        SystemShortcut systemShortcut = SystemShortcut.PRIVATE_PROFILE_INSTALL
+                .getShortcut(mTestContext, mAppInfo, mView);
+        assertNull(systemShortcut);
+    }
+
+    @Test
+    public void testPrivateProfileInstallNullPrivateProfileUser() {
+        mAppInfo = new AppInfo();
+        mAppInfo.componentName = new ComponentName(mTestContext, getClass());
+        mAppInfo.container = CONTAINER_ALL_APPS;
+        when(mPrivateProfileManager.getProfileUser()).thenReturn(null);
+
+        assertNotNull(mPrivateProfileManager);
+        assertNotNull(mAppInfo.getTargetComponent());
+        assertTrue(mAppInfo.getContainerInfo().hasAllAppsContainer());
+        assertNull(mPrivateProfileManager.getProfileUser());
+
+        SystemShortcut systemShortcut = SystemShortcut.PRIVATE_PROFILE_INSTALL
+                .getShortcut(mTestContext, mAppInfo, mView);
+
+        verify(mPrivateProfileManager, times(2)).getProfileUser();
+        assertNull(systemShortcut);
+    }
+
+    @Test
+    public void testPrivateProfileInstallNonNullPrivateProfileUser() {
+        mAppInfo = new AppInfo();
+        mAppInfo.componentName = new ComponentName(mTestContext, getClass());
+        mAppInfo.container = CONTAINER_ALL_APPS;
+        when(mPrivateProfileManager.isEnabled()).thenReturn(true);
+        when(mPrivateProfileManager.getProfileUser()).thenReturn(PRIVATE_HANDLE);
+
+        assertNotNull(mAppInfo.getTargetComponent());
+        assertTrue(mAppInfo.getContainerInfo().hasAllAppsContainer());
+        assertNotNull(mPrivateProfileManager);
+        assertNotNull(mPrivateProfileManager.getProfileUser());
+        assertNull(mTestContext.getAppsView().getAppsStore().getApp(
+                new ComponentKey(mAppInfo.getTargetComponent(), PRIVATE_HANDLE)));
+
+        SystemShortcut systemShortcut = SystemShortcut.PRIVATE_PROFILE_INSTALL
+                .getShortcut(mTestContext, mAppInfo, mView);
+
+        verify(mPrivateProfileManager, times(3)).getProfileUser();
+        verify(mPrivateProfileManager).isEnabled();
+        assertNotNull(systemShortcut);
+    }
+
+    @Test
+    public void testInstallGetShortcutWithNonWorkSpaceItemInfo() {
+        SystemShortcut systemShortcut = SystemShortcut.INSTALL.getShortcut(
+                mTestContext, mItemInfo, mView);
+        Assert.assertNull(systemShortcut);
+    }
+
+    @Test
+    @UiThreadTest
+    public void testInstallGetShortcutWithWorkSpaceItemInfo() {
+        mAppInfo = new AppInfo();
+        mAppInfo.componentName = new ComponentName(mTestContext, getClass());
+        mAppInfo.intent = mIntent;
+        WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo(mAppInfo);
+        workspaceItemInfo.status = FLAG_SUPPORTS_WEB_UI;
+        SystemShortcut systemShortcut = SystemShortcut.INSTALL.getShortcut(
+                mTestContext, workspaceItemInfo, mView);
+        Assert.assertNotNull(systemShortcut);
+    }
+
+
+    @Test
+    @DisableFlags(FLAG_ENABLE_PRIVATE_SPACE)
+    public void testUninstallGetShortcutWithPrivateSpaceOff() {
+        SystemShortcut systemShortcut = SystemShortcut.UNINSTALL_APP.getShortcut(
+                mTestContext, null, mView);
+        Assert.assertNull(systemShortcut);
+    }
+
+    @Test
+    @EnableFlags(FLAG_ENABLE_PRIVATE_SPACE)
+    public void testUninstallGetShortcutWithNonPrivateItemInfo() {
+        mAppInfo = new AppInfo();
+        mAppInfo.user = MAIN_HANDLE;
+        when(mUserIconInfo.isPrivate()).thenReturn(false);
+
+        SystemShortcut systemShortcut = SystemShortcut.UNINSTALL_APP.getShortcut(
+                mTestContext, mAppInfo, mView);
+        verify(mUserIconInfo).isPrivate();
+        Assert.assertNull(systemShortcut);
+    }
+
+    @Test
+    @EnableFlags(FLAG_ENABLE_PRIVATE_SPACE)
+    public void testUninstallGetShortcutWithSystemItemInfo() {
+        mAppInfo = new AppInfo();
+        mAppInfo.user = PRIVATE_HANDLE;
+        mAppInfo.itemType = ITEM_TYPE_APPLICATION;
+        mAppInfo.intent = mIntent;
+        mAppInfo.componentName = new ComponentName(mTestContext, getClass());
+        when(mLauncherActivityInfo.getComponentName()).thenReturn(mAppInfo.componentName);
+        when(mUserIconInfo.isPrivate()).thenReturn(true);
+        // System App
+        mApplicationInfo.flags = 1;
+
+        SystemShortcut systemShortcut = SystemShortcut.UNINSTALL_APP.getShortcut(
+                mTestContext, mAppInfo, mView);
+        verify(mLauncherActivityInfo, times(0)).getComponentName();
+        Assert.assertNull(systemShortcut);
+    }
+
+    @Test
+    @EnableFlags(FLAG_ENABLE_PRIVATE_SPACE)
+    public void testUninstallGetShortcutWithPrivateItemInfo() {
+        mAppInfo = new AppInfo();
+        mAppInfo.user = PRIVATE_HANDLE;
+        mAppInfo.itemType = ITEM_TYPE_APPLICATION;
+        mAppInfo.intent = mIntent;
+        mAppInfo.componentName = new ComponentName(mTestContext, getClass());
+        when(mUserIconInfo.isPrivate()).thenReturn(true);
+        when(mLauncherActivityInfo.getComponentName()).thenReturn(mAppInfo.componentName);
+        // 3rd party app, not system app.
+        mApplicationInfo.flags = 0;
+
+        SystemShortcut systemShortcut = SystemShortcut.UNINSTALL_APP.getShortcut(
+                mTestContext, mAppInfo, mView);
+
+        verify(mLauncherActivityInfo).getComponentName();
+        Assert.assertNotNull(systemShortcut);
+
+        systemShortcut.onClick(mView);
+        verify(mSandboxContext).startActivity(any());
+    }
+}