Merge changes from topic "p-shortcut-impl" into main

* changes:
  Widget Picker: Update the launcher integration to support shortcuts
  Widget Picker: Update UI layer to support shortcuts
  Widget Picker: Update data layer to support shortcuts
diff --git a/compose/features/com/android/launcher3/widgetpicker/WidgetPickerComposeWrapperImpl.kt b/compose/features/com/android/launcher3/widgetpicker/WidgetPickerComposeWrapperImpl.kt
index 22a47e9..c408620 100644
--- a/compose/features/com/android/launcher3/widgetpicker/WidgetPickerComposeWrapperImpl.kt
+++ b/compose/features/com/android/launcher3/widgetpicker/WidgetPickerComposeWrapperImpl.kt
@@ -18,8 +18,8 @@
 
 import android.app.Activity.RESULT_OK
 import android.content.Context
-import androidx.compose.foundation.isSystemInDarkTheme
 import android.content.Intent
+import androidx.compose.foundation.isSystemInDarkTheme
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.remember
@@ -33,7 +33,6 @@
 import com.android.launcher3.concurrent.annotations.BackgroundContext
 import com.android.launcher3.dagger.ApplicationContext
 import com.android.launcher3.util.ApiWrapper
-import com.android.launcher3.widgetpicker.WidgetPickerConfig
 import com.android.launcher3.widgetpicker.WidgetPickerConfig.Companion.EXTRA_IS_PENDING_WIDGET_DRAG
 import com.android.launcher3.widgetpicker.data.repository.WidgetAppIconsRepository
 import com.android.launcher3.widgetpicker.data.repository.WidgetUsersRepository
@@ -42,15 +41,16 @@
 import com.android.launcher3.widgetpicker.listeners.WidgetPickerDragItemListener
 import com.android.launcher3.widgetpicker.shared.model.HostConstraint
 import com.android.launcher3.widgetpicker.shared.model.WidgetHostInfo
+import com.android.launcher3.widgetpicker.shared.model.isAppWidget
+import com.android.launcher3.widgetpicker.theme.darkWidgetPickerColors
+import com.android.launcher3.widgetpicker.theme.lightWidgetPickerColors
 import com.android.launcher3.widgetpicker.ui.WidgetInteractionInfo
 import com.android.launcher3.widgetpicker.ui.WidgetPickerEventListeners
 import com.android.launcher3.widgetpicker.ui.theme.WidgetPickerTheme
-import com.android.launcher3.widgetpicker.theme.darkWidgetPickerColors
-import com.android.launcher3.widgetpicker.theme.lightWidgetPickerColors
-import kotlinx.coroutines.launch
 import javax.inject.Inject
 import javax.inject.Provider
 import kotlin.coroutines.CoroutineContext
+import kotlinx.coroutines.launch
 
 /**
  * An helper that bootstraps widget picker UI (from [WidgetPickerComponent]) in to
@@ -58,21 +58,21 @@
  *
  * Sets up the bindings necessary for widget picker component.
  */
-class WidgetPickerComposeWrapperImpl @Inject constructor(
+class WidgetPickerComposeWrapperImpl
+@Inject
+constructor(
     private val widgetPickerComponentProvider: Provider<WidgetPickerComponent.Factory>,
     private val widgetsRepository: WidgetsRepository,
     private val widgetUsersRepository: WidgetUsersRepository,
     private val widgetAppIconsRepository: WidgetAppIconsRepository,
-    @BackgroundContext
-    private val backgroundContext: CoroutineContext,
-    @ApplicationContext
-    private val appContext: Context,
+    @BackgroundContext private val backgroundContext: CoroutineContext,
+    @ApplicationContext private val appContext: Context,
     private val apiWrapper: ApiWrapper,
 ) : WidgetPickerComposeWrapper {
 
     override fun showAllWidgets(
         activity: WidgetPickerActivity,
-        widgetPickerConfig: WidgetPickerConfig
+        widgetPickerConfig: WidgetPickerConfig,
     ) {
         val widgetPickerComponent = newWidgetPickerComponent(widgetPickerConfig)
         val callbacks = activity.buildEventListeners(widgetPickerConfig, apiWrapper)
@@ -85,11 +85,12 @@
                 val scope = rememberCoroutineScope()
                 val view = LocalView.current
 
-                val widgetPickerColors = if (isSystemInDarkTheme()) {
-                    darkWidgetPickerColors()
-                } else {
-                    lightWidgetPickerColors()
-                }
+                val widgetPickerColors =
+                    if (isSystemInDarkTheme()) {
+                        darkWidgetPickerColors()
+                    } else {
+                        lightWidgetPickerColors()
+                    }
 
                 MaterialTheme { // TODO(b/408283627): Use launcher theme.
                     WidgetPickerTheme(colors = widgetPickerColors) {
@@ -99,13 +100,9 @@
                 }
 
                 DisposableEffect(view) {
-                    scope.launch {
-                        initializeRepositories()
-                    }
+                    scope.launch { initializeRepositories() }
 
-                    onDispose {
-                        cleanUpRepositories()
-                    }
+                    onDispose { cleanUpRepositories() }
                 }
             }
         }
@@ -116,19 +113,22 @@
     private fun newWidgetPickerComponent(
         widgetPickerConfig: WidgetPickerConfig
     ): WidgetPickerComponent {
-        return widgetPickerComponentProvider.get()
+        return widgetPickerComponentProvider
+            .get()
             .build(
                 widgetsRepository = widgetsRepository,
                 widgetUsersRepository = widgetUsersRepository,
                 widgetAppIconsRepository = widgetAppIconsRepository,
-                widgetHostInfo = WidgetHostInfo(
-                    title = widgetPickerConfig.title
-                        ?: appContext.resources.getString(R.string.widget_button_text),
-                    description = widgetPickerConfig.description,
-                    constraints = widgetPickerConfig.asHostConstraints(),
-                    showDragShadow = !widgetPickerConfig.isForHomeScreen
-                ),
-                backgroundContext = backgroundContext
+                widgetHostInfo =
+                    WidgetHostInfo(
+                        title =
+                            widgetPickerConfig.title
+                                ?: appContext.resources.getString(R.string.widget_button_text),
+                        description = widgetPickerConfig.description,
+                        constraints = widgetPickerConfig.asHostConstraints(),
+                        showDragShadow = !widgetPickerConfig.isForHomeScreen,
+                    ),
+                backgroundContext = backgroundContext,
             )
     }
 
@@ -150,20 +150,21 @@
 
         private fun WidgetPickerActivity.buildEventListeners(
             widgetPickerConfig: WidgetPickerConfig,
-            apiWrapper: ApiWrapper
-        ) = object : WidgetPickerEventListeners {
-            override fun onClose() {
-                finish()
-            }
+            apiWrapper: ApiWrapper,
+        ) =
+            object : WidgetPickerEventListeners {
+                override fun onClose() {
+                    finish()
+                }
 
-            override fun onWidgetInteraction(widgetInteractionInfo: WidgetInteractionInfo) {
-                if (widgetPickerConfig.isForHomeScreen) {
-                    handleWidgetInteractionForHomeScreen(widgetInteractionInfo, apiWrapper)
-                } else {
-                    handleWidgetInteractionForExternalHost(widgetInteractionInfo)
+                override fun onWidgetInteraction(widgetInteractionInfo: WidgetInteractionInfo) {
+                    if (widgetPickerConfig.isForHomeScreen) {
+                        handleWidgetInteractionForHomeScreen(widgetInteractionInfo, apiWrapper)
+                    } else {
+                        handleWidgetInteractionForExternalHost(widgetInteractionInfo)
+                    }
                 }
             }
-        }
 
         /**
          * Handles communication with the home screen about the "add" and "drag" interactions on
@@ -171,37 +172,38 @@
          *
          * For home screen, we register a listener that is called back when home screen is shown;
          * - WidgetPickerDragItemListener: bootstraps the drag helper that displays the shadow and
-         * handles the drag until completion.
+         *   handles the drag until completion.
          * - WidgetPickerAddItemListener: once launcher is shown, triggers the flow to add the
-         * widget to workspace.
+         *   widget to workspace.
          */
         private fun WidgetPickerActivity.handleWidgetInteractionForHomeScreen(
             interactionInfo: WidgetInteractionInfo,
-            apiWrapper: ApiWrapper
+            apiWrapper: ApiWrapper,
         ) {
-            val interactionListener = when (interactionInfo) {
-                is WidgetInteractionInfo.WidgetDragInfo ->
-                    WidgetPickerDragItemListener(
-                        mimeType = interactionInfo.mimeType,
-                        appWidgetProviderInfo = interactionInfo.providerInfo,
-                        widgetPreview = interactionInfo.previewInfo,
-                        previewRect = interactionInfo.bounds,
-                        previewWidth = interactionInfo.widthPx
-                    )
+            val interactionListener =
+                when (interactionInfo) {
+                    is WidgetInteractionInfo.WidgetDragInfo ->
+                        WidgetPickerDragItemListener(
+                            mimeType = interactionInfo.mimeType,
+                            widgetInfo = interactionInfo.widgetInfo,
+                            widgetPreview = interactionInfo.previewInfo,
+                            previewRect = interactionInfo.bounds,
+                            previewWidth = interactionInfo.widthPx,
+                        )
 
-                is WidgetInteractionInfo.WidgetAddInfo ->
-                    WidgetPickerAddItemListener(interactionInfo.providerInfo)
-            }
+                    is WidgetInteractionInfo.WidgetAddInfo ->
+                        WidgetPickerAddItemListener(interactionInfo.widgetInfo)
+                }
             Launcher.ACTIVITY_TRACKER.registerCallback(
                 interactionListener,
-                HOME_SCREEN_WIDGET_INTERACTION_REASON_STRING
+                HOME_SCREEN_WIDGET_INTERACTION_REASON_STRING,
             )
             startActivity(
                 /*intent=*/ Intent(Intent.ACTION_MAIN)
                     .addCategory(Intent.CATEGORY_HOME)
                     .setPackage(packageName)
                     .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
-                /*options=*/ apiWrapper.createFadeOutAnimOptions().toBundle()
+                /*options=*/ apiWrapper.createFadeOutAnimOptions().toBundle(),
             )
             finish()
         }
@@ -209,30 +211,35 @@
         /**
          * Handles communication with the external host about the "add" and "drag" interactions on
          * widgets within widget picker.
-         *
          * - In case of drag and drop, finishes the activity with result indicating that there is a
-         * pending drag [EXTRA_IS_PENDING_WIDGET_DRAG] (that would contain the widget info as part
-         * of clip data) that the host should be handling.
+         *   pending drag [EXTRA_IS_PENDING_WIDGET_DRAG] (that would contain the widget info as part
+         *   of clip data) that the host should be handling.
          * - In case of add, finishes the activity with result containing extra information about
-         * the widget being added (namely [Intent.EXTRA_COMPONENT_NAME] and [Intent.EXTRA_USER].
+         *   the widget being added (namely [Intent.EXTRA_COMPONENT_NAME] and [Intent.EXTRA_USER].
          */
         private fun WidgetPickerActivity.handleWidgetInteractionForExternalHost(
-            widgetInteractionInfo: WidgetInteractionInfo,
+            widgetInteractionInfo: WidgetInteractionInfo
         ) {
             when (widgetInteractionInfo) {
                 is WidgetInteractionInfo.WidgetDragInfo ->
-                    setResult(
-                        RESULT_OK,
-                        Intent().putExtra(EXTRA_IS_PENDING_WIDGET_DRAG, true)
-                    )
+                    setResult(RESULT_OK, Intent().putExtra(EXTRA_IS_PENDING_WIDGET_DRAG, true))
 
                 is WidgetInteractionInfo.WidgetAddInfo -> {
-                    val providerInfo = widgetInteractionInfo.providerInfo
-                    setResult(
-                        RESULT_OK, Intent()
-                            .putExtra(Intent.EXTRA_COMPONENT_NAME, providerInfo.provider)
-                            .putExtra(Intent.EXTRA_USER, providerInfo.profile)
-                    )
+                    val widgetInfo = widgetInteractionInfo.widgetInfo
+                    if (widgetInfo.isAppWidget()) {
+                        val providerInfo = widgetInfo.appWidgetProviderInfo
+                        setResult(
+                            RESULT_OK,
+                            Intent().apply {
+                                putExtra(Intent.EXTRA_COMPONENT_NAME, providerInfo.provider)
+                                putExtra(Intent.EXTRA_USER, providerInfo.profile)
+                            },
+                        )
+                    } else {
+                        throw IllegalStateException(
+                            "AppWidgetInfo not provided for external host drag"
+                        )
+                    }
                 }
             }
 
@@ -240,21 +247,21 @@
         }
 
         /** Builds the host constraints to provide to the widget picker module. */
-        fun WidgetPickerConfig.asHostConstraints() =
-            buildList {
-                if (filteredUsers.isNotEmpty()) {
-                    add(HostConstraint.HostUserConstraint(filteredUsers))
-                }
-                if (categoryInclusionFilter != 0
-                    || categoryExclusionFilter != 0
-                ) {
-                    add(
-                        HostConstraint.HostCategoryConstraint(
-                            categoryInclusionMask = categoryInclusionFilter,
-                            categoryExclusionMask = categoryExclusionFilter,
-                        )
-                    )
-                }
+        fun WidgetPickerConfig.asHostConstraints() = buildList {
+            if (filteredUsers.isNotEmpty()) {
+                add(HostConstraint.HostUserConstraint(filteredUsers))
             }
+            if (!isForHomeScreen) {
+                add(HostConstraint.NoShortcutsConstraint)
+            }
+            if (categoryInclusionFilter != 0 || categoryExclusionFilter != 0) {
+                add(
+                    HostConstraint.HostCategoryConstraint(
+                        categoryInclusionMask = categoryInclusionFilter,
+                        categoryExclusionMask = categoryExclusionFilter,
+                    )
+                )
+            }
+        }
     }
 }
diff --git a/compose/features/com/android/launcher3/widgetpicker/datasource/ConfigResourceFeaturedWidgetsDataSource.kt b/compose/features/com/android/launcher3/widgetpicker/datasource/ConfigResourceFeaturedWidgetsDataSource.kt
index d361452..5c11c7f 100644
--- a/compose/features/com/android/launcher3/widgetpicker/datasource/ConfigResourceFeaturedWidgetsDataSource.kt
+++ b/compose/features/com/android/launcher3/widgetpicker/datasource/ConfigResourceFeaturedWidgetsDataSource.kt
@@ -24,6 +24,7 @@
 import com.android.launcher3.widget.picker.util.WidgetPreviewContainerSize
 import com.android.launcher3.widgetpicker.shared.model.PickableWidget
 import com.android.launcher3.widgetpicker.shared.model.WidgetApp
+import com.android.launcher3.widgetpicker.shared.model.isAppWidget
 import java.util.Arrays
 import java.util.stream.Collectors
 import javax.inject.Inject
@@ -31,47 +32,61 @@
 /**
  * An implementation of [FeaturedWidgetsDataSource] that provides featured widgets based on a static
  * configuration from resources and pre-defined size templates.
+ *
+ * Only appwidgets; no shortcuts
  */
 @LauncherAppSingleton
-class ConfigResourceFeaturedWidgetsDataSource @Inject constructor(
+class ConfigResourceFeaturedWidgetsDataSource
+@Inject
+constructor(
     @ApplicationContext private val appContext: Context,
-    private val idp: InvariantDeviceProfile
+    private val idp: InvariantDeviceProfile,
 ) : FeaturedWidgetsDataSource {
     // the package part in component name e.g. "com.example" in {com.example/widget.Provider}
     private var eligiblePackages: Set<String> = emptySet()
 
     override suspend fun initialize() {
         if (eligiblePackages.isEmpty()) {
-            eligiblePackages = Arrays.stream(
-                appContext.resources.getStringArray(R.array.default_featured_widget_apps)
-            ).collect(Collectors.toSet())
+            eligiblePackages =
+                Arrays.stream(
+                        appContext.resources.getStringArray(R.array.default_featured_widget_apps)
+                    )
+                    .collect(Collectors.toSet())
         }
     }
 
     override suspend fun getFeaturedWidgets(widgetApps: List<WidgetApp>): List<PickableWidget> {
-        val widgetsByContainerSize = widgetApps
-            .shuffled()
-            // pick only one of user profiles
-            .distinctBy { Pair(it.id.packageName, it.id.category) }
-            .flatMap { it.widgets }
-            .filter { eligiblePackages.contains(it.id.componentName.packageName) }
-            .groupBy {
-                WidgetPreviewContainerSize(
-                    it.sizeInfo.containerSpanX,
-                    it.sizeInfo.containerSpanY
-                )
-            }
+        val widgetsByContainerSize =
+            widgetApps
+                .shuffled()
+                // pick only one of user profiles
+                .distinctBy { Pair(it.id.packageName, it.id.category) }
+                .flatMap { it.widgets }
+                .filter {
+                    eligiblePackages.isEmpty() ||
+                        eligiblePackages.contains(it.id.componentName.packageName)
+                }
+                .groupBy {
+                    WidgetPreviewContainerSize(
+                        it.sizeInfo.containerSpanX,
+                        it.sizeInfo.containerSpanY,
+                    )
+                }
 
         val selected: MutableList<PickableWidget> = mutableListOf()
         val usedAppIds: MutableSet<String> = mutableSetOf()
 
-        val sizesToPick = WidgetPreviewContainerSize.pickTemplateForFeaturedWidgets(
-            idp.getDeviceProfile(appContext)
-        )
+        val sizesToPick =
+            WidgetPreviewContainerSize.pickTemplateForFeaturedWidgets(
+                idp.getDeviceProfile(appContext)
+            )
         for (sizeToPick in sizesToPick) {
             widgetsByContainerSize[sizeToPick]?.shuffled()?.let { items ->
                 for (item in items) {
-                    if (!usedAppIds.contains(item.appId.packageName)) {
+                    if (
+                        item.widgetInfo.isAppWidget() &&
+                            !usedAppIds.contains(item.appId.packageName)
+                    ) {
                         selected.add(item)
                         usedAppIds.add(item.appId.packageName)
                         break
diff --git a/compose/features/com/android/launcher3/widgetpicker/listeners/WidgetPickerAddItemListener.kt b/compose/features/com/android/launcher3/widgetpicker/listeners/WidgetPickerAddItemListener.kt
index 330b66a..988d016 100644
--- a/compose/features/com/android/launcher3/widgetpicker/listeners/WidgetPickerAddItemListener.kt
+++ b/compose/features/com/android/launcher3/widgetpicker/listeners/WidgetPickerAddItemListener.kt
@@ -16,14 +16,17 @@
 
 package com.android.launcher3.widgetpicker.listeners
 
-import android.appwidget.AppWidgetProviderInfo
 import android.view.View
 import com.android.launcher3.Launcher
 import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_TRAY
+import com.android.launcher3.PendingAddItemInfo
 import com.android.launcher3.logging.StatsLogManager.LauncherEvent
+import com.android.launcher3.pm.ShortcutConfigActivityInfo.ShortcutConfigActivityInfoVO
 import com.android.launcher3.util.ContextTracker.SchedulerCallback
 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo
+import com.android.launcher3.widget.PendingAddShortcutInfo
 import com.android.launcher3.widget.PendingAddWidgetInfo
+import com.android.launcher3.widgetpicker.shared.model.WidgetInfo
 
 /**
  * A callback listener (for tap-to-add flow) that handles adding a widget from a separate widget
@@ -31,26 +34,38 @@
  *
  * Also logs to stats logger once widget is added.
  */
-class WidgetPickerAddItemListener(private val providerInfo: AppWidgetProviderInfo) :
+class WidgetPickerAddItemListener(private val widgetInfo: WidgetInfo) :
     SchedulerCallback<Launcher> {
     override fun init(launcher: Launcher?, isHomeStarted: Boolean): Boolean {
         checkNotNull(launcher)
 
-        val launcherProviderInfo =
-            LauncherAppWidgetProviderInfo.fromProviderInfo(launcher, providerInfo)
-        val pendingAddWidgetInfo =
-            PendingAddWidgetInfo(launcherProviderInfo, CONTAINER_WIDGETS_TRAY)
+        val pendingAddItemInfo: PendingAddItemInfo =
+            when (widgetInfo) {
+                is WidgetInfo.AppWidgetInfo -> {
+                    val launcherProviderInfo =
+                        LauncherAppWidgetProviderInfo.fromProviderInfo(
+                            launcher,
+                            widgetInfo.appWidgetProviderInfo,
+                        )
+                    PendingAddWidgetInfo(launcherProviderInfo, CONTAINER_WIDGETS_TRAY)
+                }
+
+                is WidgetInfo.ShortcutInfo ->
+                    PendingAddShortcutInfo(
+                        ShortcutConfigActivityInfoVO(widgetInfo.launcherActivityInfo)
+                    )
+            }
 
         val view = View(launcher)
-        view.tag = pendingAddWidgetInfo
+        view.tag = pendingAddItemInfo
 
         launcher.accessibilityDelegate?.addToWorkspace(
-            /*item=*/ pendingAddWidgetInfo,
-            /*accessibility=*/ false
+            /*item=*/ pendingAddItemInfo,
+            /*accessibility=*/ false,
         ) {
             launcher.statsLogManager
                 .logger()
-                .withItemInfo(pendingAddWidgetInfo)
+                .withItemInfo(pendingAddItemInfo)
                 .log(LauncherEvent.LAUNCHER_WIDGET_ADD_BUTTON_TAP)
         }
         return false // don't receive any more callbacks as we got launcher and handled it
diff --git a/compose/features/com/android/launcher3/widgetpicker/listeners/WidgetPickerDragItemListener.kt b/compose/features/com/android/launcher3/widgetpicker/listeners/WidgetPickerDragItemListener.kt
index 3b3e8c3..9d13b9b 100644
--- a/compose/features/com/android/launcher3/widgetpicker/listeners/WidgetPickerDragItemListener.kt
+++ b/compose/features/com/android/launcher3/widgetpicker/listeners/WidgetPickerDragItemListener.kt
@@ -16,72 +16,100 @@
 
 package com.android.launcher3.widgetpicker.listeners
 
-import android.appwidget.AppWidgetProviderInfo
 import android.graphics.Rect
 import android.view.View
 import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_TRAY
+import com.android.launcher3.PendingAddItemInfo
 import com.android.launcher3.dragndrop.BaseItemDragListener
+import com.android.launcher3.pm.ShortcutConfigActivityInfo.ShortcutConfigActivityInfoVO
 import com.android.launcher3.widget.DatabaseWidgetPreviewLoader.WidgetPreviewInfo
 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo
+import com.android.launcher3.widget.PendingAddShortcutInfo
 import com.android.launcher3.widget.PendingAddWidgetInfo
 import com.android.launcher3.widget.PendingItemDragHelper
+import com.android.launcher3.widgetpicker.shared.model.WidgetInfo
 import com.android.launcher3.widgetpicker.shared.model.WidgetPreview
+import com.android.launcher3.widgetpicker.shared.model.isAppWidget
 
 /**
  * A callback listener of type [BaseItemDragListener] that handles widget drag and drop from widget
  * picker hosted in a separate activity than home screen.
  *
- * Responsible for initializing the [PendingItemDragHelper] that then handles the rest of the
- * drag and drop (including showing a drag shadow for the widget).
+ * Responsible for initializing the [PendingItemDragHelper] that then handles the rest of the drag
+ * and drop (including showing a drag shadow for the widget).
  *
  * @param mimeType a mime type used by widget picker when attaching this listener for a specific
- * widget's drag and drop session.
- * @param appWidgetProviderInfo provider info of the widget being dragged
+ *   widget's drag and drop session.
+ * @param widgetInfo metadata of the widget being dragged
+ * @param widgetPreview provides the preview information for widgets
  * @param previewRect the bounds of widget's preview offset by the point of long press
  * @param previewWidth width of the preview as it appears in the widget picker.
  */
 class WidgetPickerDragItemListener(
     private val mimeType: String,
-    private val appWidgetProviderInfo: AppWidgetProviderInfo,
+    private val widgetInfo: WidgetInfo,
     private val widgetPreview: WidgetPreview,
     previewRect: Rect,
-    previewWidth: Int
+    previewWidth: Int,
 ) : BaseItemDragListener(previewRect, previewWidth, previewWidth) {
     override fun getMimeType(): String = mimeType
 
     override fun createDragHelper(): PendingItemDragHelper {
-        val launcherProviderInfo =
-            LauncherAppWidgetProviderInfo.fromProviderInfo(mLauncher, appWidgetProviderInfo)
-        val pendingAddWidgetInfo =
-            PendingAddWidgetInfo(launcherProviderInfo, CONTAINER_WIDGETS_TRAY)
+        val pendingAddItemInfo: PendingAddItemInfo =
+            when (widgetInfo) {
+                is WidgetInfo.AppWidgetInfo -> {
+                    val launcherProviderInfo =
+                        LauncherAppWidgetProviderInfo.fromProviderInfo(
+                            mLauncher,
+                            widgetInfo.appWidgetProviderInfo,
+                        )
+                    PendingAddWidgetInfo(launcherProviderInfo, CONTAINER_WIDGETS_TRAY)
+                }
+
+                is WidgetInfo.ShortcutInfo ->
+                    PendingAddShortcutInfo(
+                        ShortcutConfigActivityInfoVO(widgetInfo.launcherActivityInfo)
+                    )
+            }
 
         val view = View(mLauncher)
-        view.tag = pendingAddWidgetInfo
+        view.tag = pendingAddItemInfo
 
         val dragHelper = PendingItemDragHelper(view)
 
+        if (widgetInfo.isAppWidget()) {
+            setAppWidgetPreviewInfo(widgetPreview, widgetInfo, dragHelper)
+        } // shortcut preview is fetched by home screen.
+
+        return dragHelper
+    }
+
+    private fun setAppWidgetPreviewInfo(
+        appWidgetPreview: WidgetPreview,
+        widgetInfo: WidgetInfo.AppWidgetInfo,
+        dragHelper: PendingItemDragHelper,
+    ) {
         val info = WidgetPreviewInfo()
-        when (widgetPreview) {
+        when (appWidgetPreview) {
             is WidgetPreview.BitmapWidgetPreview -> {
-                info.previewBitmap = widgetPreview.bitmap
-                info.providerInfo = appWidgetProviderInfo
+                info.previewBitmap = appWidgetPreview.bitmap
+                info.providerInfo = widgetInfo.appWidgetProviderInfo
             }
 
             is WidgetPreview.ProviderInfoWidgetPreview -> {
-                info.providerInfo = widgetPreview.providerInfo
+                info.providerInfo = appWidgetPreview.providerInfo
             }
 
             is WidgetPreview.RemoteViewsWidgetPreview -> {
-                info.remoteViews = widgetPreview.remoteViews
-                info.providerInfo = appWidgetProviderInfo
+                info.remoteViews = appWidgetPreview.remoteViews
+                info.providerInfo = widgetInfo.appWidgetProviderInfo
             }
 
-            else -> throw IllegalStateException(
-                "Unsupported preview type when dropping widget to launcher"
-            )
+            else ->
+                throw IllegalStateException(
+                    "Unsupported preview type when dropping widget to launcher"
+                )
         }
         dragHelper.setWidgetPreviewInfo(info)
-
-        return dragHelper
     }
 }
diff --git a/compose/features/com/android/launcher3/widgetpicker/repository/WidgetsRepositoryImpl.kt b/compose/features/com/android/launcher3/widgetpicker/repository/WidgetsRepositoryImpl.kt
index a49fbc4..23ab585 100644
--- a/compose/features/com/android/launcher3/widgetpicker/repository/WidgetsRepositoryImpl.kt
+++ b/compose/features/com/android/launcher3/widgetpicker/repository/WidgetsRepositoryImpl.kt
@@ -24,6 +24,7 @@
 import com.android.launcher3.model.WidgetItem
 import com.android.launcher3.model.WidgetsModel
 import com.android.launcher3.model.data.PackageItemInfo
+import com.android.launcher3.pm.ShortcutConfigActivityInfo.ShortcutConfigActivityInfoVO
 import com.android.launcher3.util.ComponentKey
 import com.android.launcher3.util.Executors.MODEL_EXECUTOR
 import com.android.launcher3.widget.DatabaseWidgetPreviewLoader
@@ -36,8 +37,11 @@
 import com.android.launcher3.widgetpicker.shared.model.WidgetApp
 import com.android.launcher3.widgetpicker.shared.model.WidgetAppId
 import com.android.launcher3.widgetpicker.shared.model.WidgetId
+import com.android.launcher3.widgetpicker.shared.model.WidgetInfo
 import com.android.launcher3.widgetpicker.shared.model.WidgetPreview
 import com.android.launcher3.widgetpicker.shared.model.WidgetSizeInfo
+import javax.inject.Inject
+import kotlin.coroutines.CoroutineContext
 import kotlinx.coroutines.CoroutineName
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.SupervisorJob
@@ -51,76 +55,73 @@
 import kotlinx.coroutines.isActive
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
-import javax.inject.Inject
-import kotlin.coroutines.CoroutineContext
 
 /**
  * An implementation of the [WidgetsRepository] that provides widgets for widget picker using the
  * [WidgetsModel], [FeaturedWidgetsDataSource] & enables search using the provided
  * [WidgetsSearchAlgorithm].
  */
-class WidgetsRepositoryImpl @Inject constructor(
+class WidgetsRepositoryImpl
+@Inject
+constructor(
     @ApplicationContext private val appContext: Context,
     idp: InvariantDeviceProfile,
     private val widgetsModel: WidgetsModel,
     private val featuredWidgetsDataSource: FeaturedWidgetsDataSource,
     private val searchAlgorithm: WidgetsSearchAlgorithm,
-    @BackgroundContext
-    private val backgroundContext: CoroutineContext,
+    @BackgroundContext private val backgroundContext: CoroutineContext,
 ) : WidgetsRepository {
     private val deviceProfile = idp.getDeviceProfile(appContext)
-    private val backgroundScope = CoroutineScope(
-        SupervisorJob() + backgroundContext + CoroutineName("WidgetsRepository")
-    )
+    private val backgroundScope =
+        CoroutineScope(SupervisorJob() + backgroundContext + CoroutineName("WidgetsRepository"))
 
-    private val _widgetItemsByPackage =
-        MutableStateFlow<List<WidgetApp>>(emptyList())
+    private val _widgetItemsByPackage = MutableStateFlow<List<WidgetApp>>(emptyList())
     private val databaseWidgetPreviewLoader = DatabaseWidgetPreviewLoader(appContext, deviceProfile)
 
     override fun initialize() {
         // TODO(b/419495339): Remove the model executor requirement from widgets model and replace
         // with scope.launch
         MODEL_EXECUTOR.execute {
-            widgetsModel.update(/*packageUser=*/ null)
+            widgetsModel.update(/* packageUser= */ null)
             _widgetItemsByPackage.update {
                 widgetsModel.widgetsByPackageItemForPicker.toPickableWidgets(deviceProfile)
             }
         }
 
-        backgroundScope.launch {
-            featuredWidgetsDataSource.initialize()
-        }
+        backgroundScope.launch { featuredWidgetsDataSource.initialize() }
     }
 
     override fun observeWidgets(): Flow<List<WidgetApp>> = _widgetItemsByPackage.asStateFlow()
 
     override suspend fun getWidgetPreview(id: WidgetId): WidgetPreview {
         val componentKey = ComponentKey(id.componentName, id.userHandle)
-        val widgetItem = widgetsModel.widgetsByComponentKey[componentKey]
-            ?: return WidgetPreview.PlaceholderWidgetPreview
+        val widgetItem =
+            widgetsModel.widgetsByComponentKey[componentKey]
+                ?: return WidgetPreview.PlaceholderWidgetPreview
 
         val previewSizePx =
             WidgetSizes.getWidgetSizePx(deviceProfile, widgetItem.spanX, widgetItem.spanY)
-        val preview = withContext(backgroundContext) {
-            val result =
-                databaseWidgetPreviewLoader.generatePreviewInfoBg(
-                    widgetItem,
-                    previewSizePx.width,
-                    previewSizePx.height
-                )
-            when {
-                result.remoteViews != null ->
-                    WidgetPreview.RemoteViewsWidgetPreview(result.remoteViews)
+        val preview =
+            withContext(backgroundContext) {
+                val result =
+                    databaseWidgetPreviewLoader.generatePreviewInfoBg(
+                        widgetItem,
+                        previewSizePx.width,
+                        previewSizePx.height,
+                    )
+                when {
+                    result.remoteViews != null ->
+                        WidgetPreview.RemoteViewsWidgetPreview(result.remoteViews)
 
-                result.providerInfo != null ->
-                    WidgetPreview.ProviderInfoWidgetPreview(result.providerInfo)
+                    result.providerInfo != null ->
+                        WidgetPreview.ProviderInfoWidgetPreview(result.providerInfo)
 
-                result.previewBitmap != null ->
-                    WidgetPreview.BitmapWidgetPreview(result.previewBitmap)
+                    result.previewBitmap != null ->
+                        WidgetPreview.BitmapWidgetPreview(result.previewBitmap)
 
-                else -> WidgetPreview.PlaceholderWidgetPreview
+                    else -> WidgetPreview.PlaceholderWidgetPreview
+                }
             }
-        }
 
         return preview
     }
@@ -138,29 +139,32 @@
     }
 
     override fun getFeaturedWidgets(): Flow<List<PickableWidget>> {
-        return _widgetItemsByPackage.map { widgets ->
-            featuredWidgetsDataSource.getFeaturedWidgets(widgets)
-        }.flowOn(backgroundContext)
+        return _widgetItemsByPackage
+            .map { widgets -> featuredWidgetsDataSource.getFeaturedWidgets(widgets) }
+            .flowOn(backgroundContext)
     }
 
     companion object {
-        private fun Map<PackageItemInfo, List<WidgetItem>>.toPickableWidgets(deviceProfile: DeviceProfile) =
-            map { (packageItemInfo, widgetItems) ->
-                val widgetAppId = WidgetAppId(
+        private fun Map<PackageItemInfo, List<WidgetItem>>.toPickableWidgets(
+            deviceProfile: DeviceProfile
+        ) = map { (packageItemInfo, widgetItems) ->
+            val widgetAppId =
+                WidgetAppId(
                     packageName = packageItemInfo.packageName,
                     userHandle = packageItemInfo.user,
-                    category = packageItemInfo.widgetCategory
+                    category = packageItemInfo.widgetCategory,
                 )
 
-                WidgetApp(
-                    id = widgetAppId,
-                    title = packageItemInfo.title,
-                    widgets = widgetItems.filter { it.widgetInfo != null }.map { widgetItem ->
+            WidgetApp(
+                id = widgetAppId,
+                title = packageItemInfo.title,
+                widgets =
+                    widgetItems.map { widgetItem ->
                         val previewSize =
                             WidgetSizes.getWidgetSizePx(
                                 deviceProfile,
                                 widgetItem.spanX,
-                                widgetItem.spanY
+                                widgetItem.spanY,
                             )
                         val containerSpan =
                             WidgetPreviewContainerSize.forItem(widgetItem, deviceProfile)
@@ -168,31 +172,43 @@
                             WidgetSizes.getWidgetSizePx(
                                 deviceProfile,
                                 containerSpan.spanX,
-                                containerSpan.spanY
+                                containerSpan.spanY,
                             )
 
                         PickableWidget(
-                            id = WidgetId(
-                                componentName = widgetItem.componentName,
-                                userHandle = widgetItem.user
-                            ),
+                            id =
+                                WidgetId(
+                                    componentName = widgetItem.componentName,
+                                    userHandle = widgetItem.user,
+                                ),
                             appId = widgetAppId,
                             label = widgetItem.label,
                             description = widgetItem.description,
-                            appWidgetProviderInfo = widgetItem.widgetInfo.clone(),
-                            sizeInfo = WidgetSizeInfo(
-                                spanX = widgetItem.widgetInfo.spanX,
-                                spanY = widgetItem.widgetInfo.spanY,
-                                widthPx = previewSize.width,
-                                heightPx = previewSize.height,
-                                containerSpanX = containerSpan.spanX,
-                                containerSpanY = containerSpan.spanY,
-                                containerWidthPx = containerSize.width,
-                                containerHeightPx = containerSize.height
-                            )
+                            widgetInfo =
+                                if (widgetItem.widgetInfo != null) {
+                                    WidgetInfo.AppWidgetInfo(
+                                        appWidgetProviderInfo = widgetItem.widgetInfo.clone()
+                                    )
+                                } else {
+                                    check(widgetItem.activityInfo is ShortcutConfigActivityInfoVO)
+                                    WidgetInfo.ShortcutInfo(
+                                        launcherActivityInfo = widgetItem.activityInfo.mInfo
+                                    )
+                                },
+                            sizeInfo =
+                                WidgetSizeInfo(
+                                    spanX = widgetItem.spanX,
+                                    spanY = widgetItem.spanY,
+                                    widthPx = previewSize.width,
+                                    heightPx = previewSize.height,
+                                    containerSpanX = containerSpan.spanX,
+                                    containerSpanY = containerSpan.spanY,
+                                    containerWidthPx = containerSize.width,
+                                    containerHeightPx = containerSize.height,
+                                ),
                         )
-                    }
-                )
-            }
+                    },
+            )
+        }
     }
 }
diff --git a/compose/tests/com/android/launcher3/widget/AddWidgetConfigTest.kt b/compose/tests/com/android/launcher3/widget/AddWidgetConfigTest.kt
index 73daacd..288604f 100644
--- a/compose/tests/com/android/launcher3/widget/AddWidgetConfigTest.kt
+++ b/compose/tests/com/android/launcher3/widget/AddWidgetConfigTest.kt
@@ -34,6 +34,7 @@
 import com.android.launcher3.util.ui.TestViewHelpers
 import com.android.launcher3.util.workspace.FavoriteItemsTransaction
 import com.android.launcher3.widgetpicker.listeners.WidgetPickerAddItemListener
+import com.android.launcher3.widgetpicker.shared.model.WidgetInfo
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Rule
@@ -83,10 +84,10 @@
 
         // Add widget to home screen
         val monitor = WidgetConfigStartupMonitor()
-        launcherActivity.executeOnLauncher({ l: Launcher ->
-            val addItemListener = WidgetPickerAddItemListener(widgetInfo)
+        launcherActivity.executeOnLauncher { l: Launcher ->
+            val addItemListener = WidgetPickerAddItemListener(WidgetInfo.AppWidgetInfo(widgetInfo))
             addItemListener.init(l, /* isHomeStarted= */ true)
-        })
+        }
 
         uiDevice.waitForIdle()
 
diff --git a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/domain/usecase/FilterWidgetsForHostUseCase.kt b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/domain/usecase/FilterWidgetsForHostUseCase.kt
index 07de348..45f7427 100644
--- a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/domain/usecase/FilterWidgetsForHostUseCase.kt
+++ b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/domain/usecase/FilterWidgetsForHostUseCase.kt
@@ -21,8 +21,9 @@
 import com.android.launcher3.widgetpicker.shared.model.HostConstraint
 import com.android.launcher3.widgetpicker.shared.model.PickableWidget
 import com.android.launcher3.widgetpicker.shared.model.WidgetHostInfo
+import com.android.launcher3.widgetpicker.shared.model.isAppWidget
+import com.android.launcher3.widgetpicker.shared.model.isShortcut
 import javax.inject.Inject
-import javax.inject.Named
 
 /**
  * A usecase that hosts the business logic of filtering widgets based on host constraints and
@@ -34,16 +35,28 @@
 constructor(@WidgetPickerHostInfo private val hostInfo: WidgetHostInfo) {
     operator fun invoke(widgets: List<PickableWidget>) =
         widgets.filter { widget ->
+            val widgetInfo = widget.widgetInfo
+
             val eligibleForHost =
                 hostInfo.constraints.all { constraint ->
                     when (constraint) {
+                        is HostConstraint.NoShortcutsConstraint -> !widgetInfo.isShortcut()
+
                         is HostConstraint.HostUserConstraint ->
                             !constraint.userFilters.contains(widget.id.userHandle)
 
                         is HostConstraint.HostCategoryConstraint -> {
-                            val widgetCategory = widget.appWidgetProviderInfo.widgetCategory
-                            matchesCategory(constraint.categoryInclusionMask, widgetCategory) &&
-                                matchesCategory(constraint.categoryExclusionMask, widgetCategory)
+                            // category applies only to widgets
+                            if (widgetInfo.isAppWidget()) {
+                                val widgetCategory = widgetInfo.appWidgetProviderInfo.widgetCategory
+                                matchesCategory(constraint.categoryInclusionMask, widgetCategory) &&
+                                    matchesCategory(
+                                        constraint.categoryExclusionMask,
+                                        widgetCategory,
+                                    )
+                            } else {
+                                true
+                            }
                         }
                     }
                 }
diff --git a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/shared/model/PickableWidget.kt b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/shared/model/PickableWidget.kt
index 75cee6a..146692e 100644
--- a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/shared/model/PickableWidget.kt
+++ b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/shared/model/PickableWidget.kt
@@ -17,6 +17,11 @@
 package com.android.launcher3.widgetpicker.shared.model
 
 import android.appwidget.AppWidgetProviderInfo
+import android.content.pm.LauncherActivityInfo
+import com.android.launcher3.widgetpicker.shared.model.WidgetInfo.AppWidgetInfo
+import com.android.launcher3.widgetpicker.shared.model.WidgetInfo.ShortcutInfo
+import kotlin.contracts.ExperimentalContracts
+import kotlin.contracts.contract
 
 /**
  * Raw information about a widget that can be considered for display in widget picker list.
@@ -28,22 +33,22 @@
  * @property appId a unique identifier for the app group that this widget could belong to
  * @property label a user friendly label for the widget.
  * @property description a user friendly description for the widget
- * @property appWidgetProviderInfo widget info associated with the widget as configured by the
- *   developer; note: this should be a local clone and not the object that was received from
- *   appwidget manager.
+ * @property widgetInfo info associated with the widget as configured by the developer shared with
+ *   host when adding a widget; note: this should be a local clone and not the object that was
+ *   received from appwidget manager or package manager.
  */
 data class PickableWidget(
     val id: WidgetId,
     val appId: WidgetAppId,
     val label: String,
     val description: CharSequence?,
-    val appWidgetProviderInfo: AppWidgetProviderInfo,
+    val widgetInfo: WidgetInfo,
     val sizeInfo: WidgetSizeInfo,
 ) {
     // Custom toString to account for the appWidgetProviderInfo.
     override fun toString(): String =
         "PickableWidget(id=$id,appId=$appId,label=$label,description=$description," +
-            "sizeInfo=$sizeInfo,provider=${appWidgetProviderInfo.provider})"
+            "sizeInfo=$sizeInfo,widgetInfo=${widgetInfo})"
 }
 
 /**
@@ -73,3 +78,40 @@
     val containerWidthPx: Int,
     val containerHeightPx: Int,
 )
+
+/** Information of the widget as configured by the developer. */
+sealed class WidgetInfo {
+    /**
+     * @param appWidgetProviderInfo metadata of an installed widgets as received from the appwidget
+     *   manager.
+     */
+    data class AppWidgetInfo(val appWidgetProviderInfo: AppWidgetProviderInfo) : WidgetInfo()
+
+    /**
+     * @param launcherActivityInfo metadata of an installed deep shortcut as received from the
+     *   package manager.
+     */
+    data class ShortcutInfo(val launcherActivityInfo: LauncherActivityInfo) : WidgetInfo()
+
+    override fun toString(): String {
+        when (this) {
+            is AppWidgetInfo -> "WidgetInfo(provider=${this.appWidgetProviderInfo.provider})"
+            is ShortcutInfo -> "WidgetInfo(activityInfo=${this.launcherActivityInfo.componentName})"
+        }
+        return super.toString()
+    }
+}
+
+/** Returns true if the info is about an app widget. */
+@OptIn(ExperimentalContracts::class)
+fun WidgetInfo.isAppWidget(): Boolean {
+    contract { returns(true) implies (this@isAppWidget is AppWidgetInfo) }
+    return this is AppWidgetInfo
+}
+
+/** Returns true if the info is about a deep shortcut. */
+@OptIn(ExperimentalContracts::class)
+fun WidgetInfo.isShortcut(): Boolean {
+    contract { returns(true) implies (this@isShortcut is ShortcutInfo) }
+    return this is ShortcutInfo
+}
diff --git a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/shared/model/WidgetHostInfo.kt b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/shared/model/WidgetHostInfo.kt
index 3622f9f..f6b1249 100644
--- a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/shared/model/WidgetHostInfo.kt
+++ b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/shared/model/WidgetHostInfo.kt
@@ -23,17 +23,17 @@
  *
  * @param title an optional title that should be shown in place of default "Widgets" title.
  * @param description an optional 1-2 line description to be shown below the title. If not set, no
- * description is shown.
+ *   description is shown.
  * @param constraints constraints around which widgets can be shown in the picker.
  * @param showDragShadow indicates whether to show drag shadow for the widgets when dragging them;
- * can be set to false if host manages drag shadow on its own (e.g. home screen to animate the
- * shadow with actual content)
+ *   can be set to false if host manages drag shadow on its own (e.g. home screen to animate the
+ *   shadow with actual content)
  */
 data class WidgetHostInfo(
     val title: String? = null,
     val description: String? = null,
     val constraints: List<HostConstraint> = emptyList(),
-    val showDragShadow: Boolean = true
+    val showDragShadow: Boolean = true,
 )
 
 /** Various constraints for the widget host. */
@@ -60,4 +60,7 @@
      *   such case, the profile tab shows a generic no widgets available message.
      */
     data class HostUserConstraint(val userFilters: List<UserHandle>) : HostConstraint()
+
+    /** Indicates that the host doesn't support shortcuts. */
+    data object NoShortcutsConstraint : HostConstraint()
 }
diff --git a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/ui/WidgetPickerEventListeners.kt b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/ui/WidgetPickerEventListeners.kt
index 9973b79..e515e22 100644
--- a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/ui/WidgetPickerEventListeners.kt
+++ b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/ui/WidgetPickerEventListeners.kt
@@ -16,13 +16,13 @@
 
 package com.android.launcher3.widgetpicker.ui
 
-import android.appwidget.AppWidgetProviderInfo
 import android.graphics.Rect
+import com.android.launcher3.widgetpicker.shared.model.WidgetInfo
 import com.android.launcher3.widgetpicker.shared.model.WidgetPreview
 
 /**
- * General interface that clients can implement to listen to events from different types of
- * widget picker.
+ * General interface that clients can implement to listen to events from different types of widget
+ * picker.
  */
 interface WidgetPickerEventListeners {
     /** Called when the widget picker is dismissed. */
@@ -37,7 +37,7 @@
     /**
      * Information passed in event listener when a widget is dragged.
      *
-     * @param providerInfo metadata for the provider of the widget being dragged.
+     * @param widgetInfo metadata for the provider of the widget being dragged.
      * @param bounds current bounds of the widget's preview considering the drag offset and scale.
      * @param widthPx measured width of the preview.
      * @param heightPx measured height of the preview.
@@ -45,7 +45,7 @@
      * @param mimeType a unique mime type set on clip data for the drag session
      */
     data class WidgetDragInfo(
-        val providerInfo: AppWidgetProviderInfo,
+        val widgetInfo: WidgetInfo,
         val bounds: Rect,
         val widthPx: Int,
         val heightPx: Int,
@@ -56,9 +56,7 @@
     /**
      * Information passed in event listener when a widget is added using tap to add.
      *
-     * @param providerInfo metadata for the provider of the widget being added.
+     * @param widgetInfo metadata for the provider of the widget being added.
      */
-    data class WidgetAddInfo(
-        val providerInfo: AppWidgetProviderInfo
-    ) : WidgetInteractionInfo()
+    data class WidgetAddInfo(val widgetInfo: WidgetInfo) : WidgetInteractionInfo()
 }
diff --git a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/ui/components/DragAndDrop.kt b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/ui/components/DragAndDrop.kt
index 309eb0f..8dc7938 100644
--- a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/ui/components/DragAndDrop.kt
+++ b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/ui/components/DragAndDrop.kt
@@ -16,15 +16,16 @@
 
 package com.android.launcher3.widgetpicker.ui.components
 
-import android.appwidget.AppWidgetProviderInfo
 import android.content.ClipData
 import android.content.ClipDescription
+import android.content.ComponentName
 import android.content.Context
 import android.content.Intent
 import android.graphics.Bitmap
 import android.graphics.Canvas
 import android.graphics.Point
 import android.graphics.Rect
+import android.os.UserHandle
 import android.view.View
 import android.view.View.DragShadowBuilder
 import androidx.compose.ui.unit.Dp
@@ -32,33 +33,31 @@
 import androidx.compose.ui.unit.IntSize
 import androidx.core.graphics.drawable.RoundedBitmapDrawable
 import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
+import com.android.launcher3.widgetpicker.shared.model.WidgetInfo
 import java.util.UUID
 
-/**
- * Information about the image's dimensions post scaling.
- */
+/** Information about the image's dimensions post scaling. */
 data class ImageScaledDimensions(
     val scale: Float,
     val scaledSizeDp: DpSize,
     val scaledSizePx: IntSize,
     val scaledRadiusDp: Dp,
-    val scaledRadiusPx: Float
+    val scaledRadiusPx: Float,
 )
 
-/**
- * A [DragShadowBuilder] that draws drag shadow using the provided bitmap and image dimensions.
- */
+/** A [DragShadowBuilder] that draws drag shadow using the provided bitmap and image dimensions. */
 class ImageBitmapDragShadowBuilder(
     context: Context,
     bitmap: Bitmap,
-    imageScaledDimensions: ImageScaledDimensions
+    imageScaledDimensions: ImageScaledDimensions,
 ) : DragShadowBuilder() {
     private val shadowWidth = imageScaledDimensions.scaledSizePx.width
     private val shadowHeight = imageScaledDimensions.scaledSizePx.height
 
     private val shadowDrawable: RoundedBitmapDrawable =
-        RoundedBitmapDrawableFactory.create(context.resources, bitmap)
-            .apply { cornerRadius = imageScaledDimensions.scaledRadiusPx }
+        RoundedBitmapDrawableFactory.create(context.resources, bitmap).apply {
+            cornerRadius = imageScaledDimensions.scaledRadiusPx
+        }
 
     override fun onProvideShadowMetrics(outShadowSize: Point?, outShadowTouchPoint: Point?) {
         outShadowSize?.set(shadowWidth, shadowHeight)
@@ -84,48 +83,62 @@
     private const val SHADOW_SIZE = 10
 
     override fun onDrawShadow(canvas: Canvas) {}
+
     override fun onProvideShadowMetrics(outShadowSize: Point, outShadowTouchPoint: Point) {
-        outShadowSize.set(SHADOW_SIZE, SHADOW_SIZE);
-        outShadowTouchPoint.set(SHADOW_SIZE / 2, SHADOW_SIZE / 2);
+        outShadowSize.set(SHADOW_SIZE, SHADOW_SIZE)
+        outShadowTouchPoint.set(SHADOW_SIZE / 2, SHADOW_SIZE / 2)
     }
 }
 
-/**  State containing information to start a drag for a widget. */
+/** State containing information to start a drag for a widget. */
 class DragState(
-    private val widgetInfo: AppWidgetProviderInfo,
-    private val dragShadowBuilder: DragShadowBuilder
+    private val widgetInfo: WidgetInfo,
+    private val dragShadowBuilder: DragShadowBuilder,
 ) {
     private val uniqueId = UUID.randomUUID().toString()
     val pickerMimeType = "com.android.launcher3.widgetpicker.drag_and_drop/$uniqueId"
 
     fun startDrag(view: View) {
-        val clipData = ClipData(
-            ClipDescription(
-                // not displayed anywhere; so, set to empty.
-                /* label= */ "",
-                arrayOf(
-                    // unique picker specific mime type.
-                    pickerMimeType,
-                    // indicates that the clip item contains an intent (with extras about widget
-                    // info).
-                    ClipDescription.MIMETYPE_TEXT_INTENT
-                )
-            ),
-            ClipData.Item(
-                Intent()
-                    .putExtra(Intent.EXTRA_USER, widgetInfo.profile)
-                    .putExtra(
-                        Intent.EXTRA_COMPONENT_NAME,
-                        widgetInfo.provider
-                    )
+        val clipData =
+            ClipData(
+                ClipDescription(
+                    // not displayed anywhere; so, set to empty.
+                    /* label= */ "",
+                    arrayOf(
+                        // unique picker specific mime type.
+                        pickerMimeType,
+                        // indicates that the clip item contains an intent (with extras about widget
+                        // info).
+                        ClipDescription.MIMETYPE_TEXT_INTENT,
+                    ),
+                ),
+                ClipData.Item(
+                    when (widgetInfo) {
+                        is WidgetInfo.AppWidgetInfo ->
+                            buildIntentForClipData(
+                                user = widgetInfo.appWidgetProviderInfo.profile,
+                                componentName = widgetInfo.appWidgetProviderInfo.provider,
+                            )
+
+                        is WidgetInfo.ShortcutInfo ->
+                            buildIntentForClipData(
+                                user = widgetInfo.launcherActivityInfo.user,
+                                componentName = widgetInfo.launcherActivityInfo.componentName,
+                            )
+                    }
+                ),
             )
-        )
 
         view.startDragAndDrop(
             clipData,
             /*shadowBuilder=*/ dragShadowBuilder,
             /*myLocalState=*/ null,
-            View.DRAG_FLAG_GLOBAL
+            View.DRAG_FLAG_GLOBAL,
         )
     }
+
+    private fun buildIntentForClipData(user: UserHandle, componentName: ComponentName): Intent =
+        Intent()
+            .putExtra(Intent.EXTRA_USER, user)
+            .putExtra(Intent.EXTRA_COMPONENT_NAME, componentName)
 }
diff --git a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/ui/components/WidgetDetails.kt b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/ui/components/WidgetDetails.kt
index 4edcdfd..0ad64f8 100644
--- a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/ui/components/WidgetDetails.kt
+++ b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/ui/components/WidgetDetails.kt
@@ -36,7 +36,6 @@
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Add
 import androidx.compose.material3.Button
-import androidx.compose.material3.ButtonColors
 import androidx.compose.material3.ButtonDefaults
 import androidx.compose.material3.Icon
 import androidx.compose.material3.Text
@@ -90,61 +89,56 @@
 ) {
     val haptic = LocalHapticFeedback.current
     val interactionSource = remember { MutableInteractionSource() }
-    val contentDescription = stringResource(
-        R.string.widget_details_accessibility_label,
-        widget.label,
-        widget.sizeInfo.spanX,
-        widget.sizeInfo.spanY
-    )
+    val contentDescription =
+        stringResource(
+            R.string.widget_details_accessibility_label,
+            widget.label,
+            widget.sizeInfo.spanX,
+            widget.sizeInfo.spanY,
+        )
 
-    val detailsAlpha: Float by animateFloatAsState(
-        targetValue = if (showAddButton) INVISIBLE_ALPHA else VISIBLE_ALPHA,
-        animationSpec = tween(durationMillis = TOGGLE_ANIMATION_DURATION),
-        label = "detailsAlphaAnimation"
-    )
+    val detailsAlpha: Float by
+        animateFloatAsState(
+            targetValue = if (showAddButton) INVISIBLE_ALPHA else VISIBLE_ALPHA,
+            animationSpec = tween(durationMillis = TOGGLE_ANIMATION_DURATION),
+            label = "detailsAlphaAnimation",
+        )
 
     Box(
         contentAlignment = Alignment.Center,
-        modifier = modifier
-            .fillMaxSize()
-            .clickable(
-                onClickLabel = if (showAddButton) {
-                    stringResource(R.string.widget_tap_to_hide_add_button_label)
-                } else {
-                    stringResource(R.string.widget_tap_to_show_add_button_label)
-                },
-                interactionSource = interactionSource,
-                indication = null
-            ) {
-                haptic.performHapticFeedback(HapticFeedbackType.VirtualKey)
-                onAddButtonToggle(
-                    widget.id
-                )
-            }
-            .padding(
-                horizontal = WidgetDetailsDimensions.horizontalPadding,
-                vertical = WidgetDetailsDimensions.verticalPadding
-            )
+        modifier =
+            modifier
+                .fillMaxSize()
+                .clickable(
+                    onClickLabel =
+                        if (showAddButton) {
+                            stringResource(R.string.widget_tap_to_hide_add_button_label)
+                        } else {
+                            stringResource(R.string.widget_tap_to_show_add_button_label)
+                        },
+                    interactionSource = interactionSource,
+                    indication = null,
+                ) {
+                    haptic.performHapticFeedback(HapticFeedbackType.VirtualKey)
+                    onAddButtonToggle(widget.id)
+                }
+                .padding(
+                    horizontal = WidgetDetailsDimensions.horizontalPadding,
+                    vertical = WidgetDetailsDimensions.verticalPadding,
+                ),
     ) {
         Column(
             horizontalAlignment = Alignment.CenterHorizontally,
             verticalArrangement = Arrangement.Top,
-            modifier = Modifier
-                .clearAndSetSemantics { this.contentDescription = contentDescription }
-                .minimumInteractiveComponentSize()
-                .graphicsLayer { alpha = detailsAlpha }
-                .fillMaxSize()
+            modifier =
+                Modifier.clearAndSetSemantics { this.contentDescription = contentDescription }
+                    .minimumInteractiveComponentSize()
+                    .graphicsLayer { alpha = detailsAlpha }
+                    .fillMaxSize(),
         ) {
-            WidgetLabel(
-                label = widget.label,
-                appIcon = appIcon,
-                modifier = Modifier
-            )
+            WidgetLabel(label = widget.label, appIcon = appIcon, modifier = Modifier)
             if (showAllDetails) {
-                WidgetSpanSizeLabel(
-                    spanX = widget.sizeInfo.spanX,
-                    spanY = widget.sizeInfo.spanY
-                )
+                WidgetSpanSizeLabel(spanX = widget.sizeInfo.spanX, spanY = widget.sizeInfo.spanY)
                 widget.description?.let { WidgetDescription(it) }
             }
         }
@@ -152,16 +146,12 @@
             visible = showAddButton,
             modifier = Modifier.fillMaxSize(),
             enter = AddButtonDefaults.enterTransition,
-            exit = AddButtonDefaults.exitTransition
+            exit = AddButtonDefaults.exitTransition,
         ) {
             AddButton(
                 widget = widget,
                 onClick = {
-                    onWidgetAddClick(
-                        WidgetInteractionInfo.WidgetAddInfo(
-                            widget.appWidgetProviderInfo
-                        )
-                    )
+                    onWidgetAddClick(WidgetInteractionInfo.WidgetAddInfo(widget.widgetInfo))
                     haptic.performHapticFeedback(HapticFeedbackType.Confirm)
                 },
             )
@@ -170,33 +160,28 @@
 }
 
 @Composable
-private fun AddButton(
-    widget: PickableWidget,
-    onClick: () -> Unit,
-) {
+private fun AddButton(widget: PickableWidget, onClick: () -> Unit) {
     val accessibleDescription =
         stringResource(R.string.widget_tap_to_add_button_content_description, widget.label)
 
-    Box(
-        modifier = Modifier.fillMaxSize(),
-        contentAlignment = Alignment.Center
-    ) {
+    Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
         Button(
             modifier = Modifier.minimumInteractiveComponentSize(),
             contentPadding = AddButtonDimensions.paddingValues,
-            colors = ButtonDefaults.buttonColors(
-                containerColor = WidgetPickerTheme.colors.addButtonBackground,
-                contentColor = WidgetPickerTheme.colors.addButtonContent
-            ),
+            colors =
+                ButtonDefaults.buttonColors(
+                    containerColor = WidgetPickerTheme.colors.addButtonBackground,
+                    contentColor = WidgetPickerTheme.colors.addButtonContent,
+                ),
             onClick = onClick,
         ) {
             Icon(
                 imageVector = Icons.Filled.Add,
-                contentDescription = null // decorative
+                contentDescription = null, // decorative
             )
             Text(
                 modifier = Modifier.semantics { this.contentDescription = accessibleDescription },
-                text = stringResource(R.string.widget_tap_to_add_button_label)
+                text = stringResource(R.string.widget_tap_to_add_button_label),
             )
         }
     }
@@ -208,15 +193,13 @@
     Row(
         modifier = modifier,
         horizontalArrangement = Arrangement.Center,
-        verticalAlignment = Alignment.CenterVertically
+        verticalAlignment = Alignment.CenterVertically,
     ) {
         if (appIcon != null) {
             appIcon()
             Spacer(
                 modifier =
-                    Modifier
-                        .width(WidgetDetailsDimensions.appIconLabelSpacing)
-                        .fillMaxHeight()
+                    Modifier.width(WidgetDetailsDimensions.appIconLabelSpacing).fillMaxHeight()
             )
         }
         Text(
@@ -272,12 +255,7 @@
 }
 
 private object AddButtonDimensions {
-    val paddingValues = PaddingValues(
-        start = 8.dp,
-        top = 11.dp,
-        end = 16.dp,
-        bottom = 11.dp
-    )
+    val paddingValues = PaddingValues(start = 8.dp, top = 11.dp, end = 16.dp, bottom = 11.dp)
 }
 
 private object AddButtonDefaults {
diff --git a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/ui/components/WidgetPreview.kt b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/ui/components/WidgetPreview.kt
index 7977dd2..2647ef7 100644
--- a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/ui/components/WidgetPreview.kt
+++ b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/ui/components/WidgetPreview.kt
@@ -63,8 +63,10 @@
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.viewinterop.AndroidView
 import com.android.launcher3.widgetpicker.shared.model.WidgetId
+import com.android.launcher3.widgetpicker.shared.model.WidgetInfo
 import com.android.launcher3.widgetpicker.shared.model.WidgetPreview
 import com.android.launcher3.widgetpicker.shared.model.WidgetSizeInfo
+import com.android.launcher3.widgetpicker.shared.model.isAppWidget
 import com.android.launcher3.widgetpicker.ui.WidgetInteractionInfo
 import com.android.launcher3.widgetpicker.ui.theme.WidgetPickerTheme
 import kotlin.math.roundToInt
@@ -75,11 +77,11 @@
     id: WidgetId,
     sizeInfo: WidgetSizeInfo,
     preview: WidgetPreview,
-    appwidgetInfo: AppWidgetProviderInfo,
+    widgetInfo: WidgetInfo,
     modifier: Modifier = Modifier,
     showDragShadow: Boolean,
     onWidgetInteraction: (WidgetInteractionInfo) -> Unit,
-    onAddButtonToggle: (WidgetId) -> Unit
+    onAddButtonToggle: (WidgetId) -> Unit,
 ) {
     val interactionSource = remember { MutableInteractionSource() }
     val haptic = LocalHapticFeedback.current
@@ -93,16 +95,16 @@
         }
 
     Box(
-        modifier = modifier
-            .wrapContentSize()
-            .clickable(
+        modifier =
+            modifier.wrapContentSize().clickable(
                 interactionSource = interactionSource,
                 // no ripples for preview taps that toggle the add button.
-                indication = null
+                indication = null,
             ) {
                 haptic.performHapticFeedback(HapticFeedbackType.VirtualKey)
                 onAddButtonToggle(id)
-            }) {
+            }
+    ) {
         when (preview) {
             is WidgetPreview.PlaceholderWidgetPreview ->
                 PlaceholderWidgetPreview(size = containerSize, widgetRadius = widgetRadius)
@@ -112,30 +114,34 @@
                     bitmap = preview.bitmap,
                     size = containerSize,
                     widgetRadius = widgetRadius,
-                    widgetInfo = appwidgetInfo,
+                    widgetInfo = widgetInfo,
                     showDragShadow = showDragShadow,
                     onWidgetInteraction = onWidgetInteraction,
                 )
 
-            is WidgetPreview.RemoteViewsWidgetPreview ->
+            is WidgetPreview.RemoteViewsWidgetPreview -> {
+                check(widgetInfo.isAppWidget())
                 RemoteViewsWidgetPreview(
                     remoteViews = preview.remoteViews,
-                    widgetInfo = appwidgetInfo,
+                    widgetInfo = widgetInfo,
                     sizeInfo = sizeInfo,
                     widgetRadius = widgetRadius,
                     showDragShadow = showDragShadow,
                     onWidgetInteraction = onWidgetInteraction,
                 )
+            }
 
-            is WidgetPreview.ProviderInfoWidgetPreview ->
+            is WidgetPreview.ProviderInfoWidgetPreview -> {
+                check(widgetInfo.isAppWidget())
                 RemoteViewsWidgetPreview(
                     previewLayoutProviderInfo = preview.providerInfo,
-                    widgetInfo = appwidgetInfo,
+                    widgetInfo = widgetInfo,
                     sizeInfo = sizeInfo,
                     widgetRadius = widgetRadius,
                     showDragShadow = showDragShadow,
                     onWidgetInteraction = onWidgetInteraction,
                 )
+            }
         }
     }
 }
@@ -145,8 +151,7 @@
     Box(
         contentAlignment = Alignment.Center,
         modifier =
-            Modifier
-                .width(size.width)
+            Modifier.width(size.width)
                 .height(size.height)
                 .background(
                     color = WidgetPickerTheme.colors.widgetPlaceholderBackground,
@@ -161,7 +166,7 @@
 private fun BitmapWidgetPreview(
     bitmap: Bitmap,
     size: DpSize,
-    widgetInfo: AppWidgetProviderInfo,
+    widgetInfo: WidgetInfo,
     widgetRadius: Dp,
     showDragShadow: Boolean,
     onWidgetInteraction: (WidgetInteractionInfo) -> Unit,
@@ -170,22 +175,24 @@
     val density = LocalDensity.current
     val haptic = LocalHapticFeedback.current
 
-    val scaledBitmapDimensions by remember(bitmap, density, size) {
-        derivedStateOf { bitmap.calculateScaledDimensions(density, size, widgetRadius) }
-    }
-
-    val dragState by remember(widgetInfo, showDragShadow) {
-        derivedStateOf {
-            DragState(
-                widgetInfo,
-                if (showDragShadow) {
-                    ImageBitmapDragShadowBuilder(context, bitmap, scaledBitmapDimensions)
-                } else {
-                    TransparentDragShadowBuilder
-                }
-            )
+    val scaledBitmapDimensions by
+        remember(bitmap, density, size) {
+            derivedStateOf { bitmap.calculateScaledDimensions(density, size, widgetRadius) }
         }
-    }
+
+    val dragState by
+        remember(widgetInfo, showDragShadow) {
+            derivedStateOf {
+                DragState(
+                    widgetInfo,
+                    if (showDragShadow) {
+                        ImageBitmapDragShadowBuilder(context, bitmap, scaledBitmapDimensions)
+                    } else {
+                        TransparentDragShadowBuilder
+                    },
+                )
+            }
+        }
 
     var imagePositionInParent by remember { mutableStateOf(Offset.Zero) }
 
@@ -199,8 +206,7 @@
         contentDescription = null, // only visual (widget details provides the readable info)
         contentScale = ContentScale.FillBounds,
         modifier =
-            Modifier
-                .onGloballyPositioned { coordinates ->
+            Modifier.onGloballyPositioned { coordinates ->
                     imagePositionInParent = coordinates.positionInParent()
                 }
                 .pointerInput(bitmap) {
@@ -215,21 +221,19 @@
                                 calculateImageDragBounds(
                                     scaledBitmapDimensions = scaledBitmapDimensions,
                                     imagePositionInParent = imagePositionInParent,
-                                    offset = offset
+                                    offset = offset,
                                 )
                             onWidgetInteraction(
                                 WidgetInteractionInfo.WidgetDragInfo(
                                     mimeType = dragState.pickerMimeType,
-                                    providerInfo = widgetInfo,
+                                    widgetInfo = widgetInfo,
                                     bounds = bounds,
                                     widthPx = scaledBitmapDimensions.scaledSizePx.width,
                                     heightPx = scaledBitmapDimensions.scaledSizePx.height,
-                                    previewInfo = WidgetPreview.BitmapWidgetPreview(
-                                        bitmap = bitmap,
-                                    ),
+                                    previewInfo = WidgetPreview.BitmapWidgetPreview(bitmap = bitmap),
                                 )
                             )
-                        }
+                        },
                     )
                 }
                 .width(scaledBitmapDimensions.scaledSizeDp.width)
@@ -242,26 +246,20 @@
 private fun calculateImageDragBounds(
     scaledBitmapDimensions: ImageScaledDimensions,
     imagePositionInParent: Offset,
-    offset: Offset
+    offset: Offset,
 ): Rect {
     val bounds = Rect()
     bounds.left = 0
     bounds.top = 0
     bounds.right = scaledBitmapDimensions.scaledSizePx.width
     bounds.bottom = scaledBitmapDimensions.scaledSizePx.height
-    val xOffset: Int =
-        (imagePositionInParent.x - offset.x).roundToInt()
-    val yOffset: Int =
-        (imagePositionInParent.y - offset.y).roundToInt()
+    val xOffset: Int = (imagePositionInParent.x - offset.x).roundToInt()
+    val yOffset: Int = (imagePositionInParent.y - offset.y).roundToInt()
     bounds.offset(xOffset, yOffset)
     return bounds
 }
 
-private fun Bitmap.calculateScaledDimensions(
-    density: Density,
-    size: DpSize,
-    widgetRadius: Dp
-) =
+private fun Bitmap.calculateScaledDimensions(density: Density, size: DpSize, widgetRadius: Dp) =
     with(density) {
         val bitmapSize = DpSize(width = width.toDp(), height = height.toDp())
         val bitmapAspectRatio = bitmapSize.width / bitmapSize.height
@@ -269,20 +267,20 @@
 
         // Scale by width if image has larger aspect ratio than the container else by
         // height; and avoid cropping the previews.
-        val scale = if (bitmapAspectRatio > containerAspectRatio) {
-            size.width / bitmapSize.width
-        } else {
-            size.height / bitmapSize.height
-        }
+        val scale =
+            if (bitmapAspectRatio > containerAspectRatio) {
+                size.width / bitmapSize.width
+            } else {
+                size.height / bitmapSize.height
+            }
 
-        val scaledDpSize = DpSize(
-            width = bitmapSize.width * scale,
-            height = bitmapSize.height * scale
-        )
-        val scaledPxSize = IntSize(
-            width = scaledDpSize.width.roundToPx(),
-            height = scaledDpSize.height.roundToPx()
-        )
+        val scaledDpSize =
+            DpSize(width = bitmapSize.width * scale, height = bitmapSize.height * scale)
+        val scaledPxSize =
+            IntSize(
+                width = scaledDpSize.width.roundToPx(),
+                height = scaledDpSize.height.roundToPx(),
+            )
         val scaledRadius = (widgetRadius * scale).coerceAtMost(widgetRadius).value.roundToInt().dp
 
         ImageScaledDimensions(
@@ -290,7 +288,7 @@
             scaledSizePx = scaledPxSize,
             scaledSizeDp = scaledDpSize,
             scaledRadiusDp = scaledRadius,
-            scaledRadiusPx = scaledRadius.toPx()
+            scaledRadiusPx = scaledRadius.toPx(),
         )
     }
 
@@ -298,7 +296,7 @@
 private fun RemoteViewsWidgetPreview(
     remoteViews: RemoteViews? = null,
     previewLayoutProviderInfo: AppWidgetProviderInfo? = null,
-    widgetInfo: AppWidgetProviderInfo,
+    widgetInfo: WidgetInfo.AppWidgetInfo,
     sizeInfo: WidgetSizeInfo,
     widgetRadius: Dp,
     onWidgetInteraction: (WidgetInteractionInfo) -> Unit,
@@ -308,67 +306,71 @@
     val haptic = LocalHapticFeedback.current
 
     val appWidgetHostView by
-    remember(sizeInfo, widgetInfo) {
-        derivedStateOf {
-            WidgetPreviewHostView(context).apply {
-                setContainerSizePx(
-                    IntSize(sizeInfo.containerWidthPx, sizeInfo.containerHeightPx)
-                )
+        remember(sizeInfo, widgetInfo) {
+            derivedStateOf {
+                WidgetPreviewHostView(context).apply {
+                    setContainerSizePx(
+                        IntSize(sizeInfo.containerWidthPx, sizeInfo.containerHeightPx)
+                    )
+                }
             }
         }
-    }
 
     val dragState by remember {
         derivedStateOf {
             DragState(
                 widgetInfo = widgetInfo,
-                dragShadowBuilder = if (showDragShadow) {
-                    DragShadowBuilder(appWidgetHostView)
-                } else {
-                    TransparentDragShadowBuilder
-                }
+                dragShadowBuilder =
+                    if (showDragShadow) {
+                        DragShadowBuilder(appWidgetHostView)
+                    } else {
+                        TransparentDragShadowBuilder
+                    },
             )
         }
     }
 
     key(appWidgetHostView) {
         AndroidView(
-            modifier = Modifier
-                .pointerInput(appWidgetHostView) {
-                    detectDragGesturesAfterLongPress(
-                        onDrag = { change, _ -> change.consume() },
-                        onDragStart = { offset ->
-                            haptic.performHapticFeedback(HapticFeedbackType.LongPress)
-                            dragState.startDrag(appWidgetHostView)
+            modifier =
+                Modifier.pointerInput(appWidgetHostView) {
+                        detectDragGesturesAfterLongPress(
+                            onDrag = { change, _ -> change.consume() },
+                            onDragStart = { offset ->
+                                haptic.performHapticFeedback(HapticFeedbackType.LongPress)
+                                dragState.startDrag(appWidgetHostView)
 
-                            onWidgetInteraction(
-                                WidgetInteractionInfo.WidgetDragInfo(
-                                    mimeType = dragState.pickerMimeType,
-                                    providerInfo = widgetInfo,
-                                    bounds = appWidgetHostView.getDragBoundsForOffset(offset),
-                                    widthPx = appWidgetHostView.measuredWidth,
-                                    heightPx = appWidgetHostView.measuredHeight,
-                                    previewInfo = when {
-                                        remoteViews != null ->
-                                            WidgetPreview.RemoteViewsWidgetPreview(
-                                                remoteViews = remoteViews,
-                                            )
+                                onWidgetInteraction(
+                                    WidgetInteractionInfo.WidgetDragInfo(
+                                        mimeType = dragState.pickerMimeType,
+                                        widgetInfo = widgetInfo,
+                                        bounds = appWidgetHostView.getDragBoundsForOffset(offset),
+                                        widthPx = appWidgetHostView.measuredWidth,
+                                        heightPx = appWidgetHostView.measuredHeight,
+                                        previewInfo =
+                                            when {
+                                                remoteViews != null ->
+                                                    WidgetPreview.RemoteViewsWidgetPreview(
+                                                        remoteViews = remoteViews
+                                                    )
 
-                                        previewLayoutProviderInfo != null ->
-                                            WidgetPreview.ProviderInfoWidgetPreview(
-                                                providerInfo = previewLayoutProviderInfo
-                                            )
+                                                previewLayoutProviderInfo != null ->
+                                                    WidgetPreview.ProviderInfoWidgetPreview(
+                                                        providerInfo = previewLayoutProviderInfo
+                                                    )
 
-                                        else ->
-                                            throw IllegalStateException("No preview during drag")
-                                    }
+                                                else ->
+                                                    throw IllegalStateException(
+                                                        "No preview during drag"
+                                                    )
+                                            },
+                                    )
                                 )
-                            )
-                        },
-                    )
-                }
-                .wrapContentSize()
-                .clip(RoundedCornerShape(widgetRadius)),
+                            },
+                        )
+                    }
+                    .wrapContentSize()
+                    .clip(RoundedCornerShape(widgetRadius)),
             factory = { appWidgetHostView },
             update = { view ->
                 // if preview.remoteViews is null, initial layout will render.
@@ -376,7 +378,7 @@
                 // to be the previewLayout.
                 view.setAppWidget(
                     /*appWidgetId=*/ NO_OP_APP_WIDGET_ID,
-                    /*info=*/ previewLayoutProviderInfo ?: widgetInfo,
+                    /*info=*/ previewLayoutProviderInfo ?: widgetInfo.appWidgetProviderInfo,
                 )
                 view.updateAppWidget(remoteViews)
             },
diff --git a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/ui/components/WidgetsGrid.kt b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/ui/components/WidgetsGrid.kt
index 5e0ecf8..4426ab7 100644
--- a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/ui/components/WidgetsGrid.kt
+++ b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/ui/components/WidgetsGrid.kt
@@ -61,10 +61,10 @@
  * @param appIcons optional map containing app icons to show in the widget details besides the label
  *   (when showing the widgets outside of app context e.g. recommendations)
  * @param showDragShadow indicates if in a drag and drop session, widget picker should show drag
- * shadow containing the preview; if not set, a transparent shadow is rendered and host should
- * manage providing a shadow on its own.
+ *   shadow containing the preview; if not set, a transparent shadow is rendered and host should
+ *   manage providing a shadow on its own.
  * @param onWidgetInteraction callback invoked when a widget is being dragged and picker has started
- * global drag and drop session.
+ *   global drag and drop session.
  * @param modifier modifier with parent constraints and additional modifications
  */
 @Composable
@@ -93,12 +93,13 @@
                 addButtonWidgetId = addButtonWidgetId,
                 onWidgetInteraction = onWidgetInteraction,
                 onAddButtonToggle = { id ->
-                    addButtonWidgetId = if (id != addButtonWidgetId) {
-                        id
-                    } else {
-                        null
-                    }
-                }
+                    addButtonWidgetId =
+                        if (id != addButtonWidgetId) {
+                            id
+                        } else {
+                            null
+                        }
+                },
             )
         }
     }
@@ -155,7 +156,7 @@
                 appIcons = appIcons,
                 addButtonWidgetId = addButtonWidgetId,
                 onWidgetInteraction = onWidgetInteraction,
-                onAddButtonToggle = onAddButtonToggle
+                onAddButtonToggle = onAddButtonToggle,
             )
         },
         previewContainerWidthPx = widgetSizeGroup.previewContainerWidthPx,
@@ -184,21 +185,19 @@
         Box(
             contentAlignment = Alignment.BottomCenter,
             modifier =
-                Modifier
-                    .fillMaxSize()
-                    .clearAndSetSemantics {
-                        traversalIndex = index.toFloat()
-                        testTag = buildWidgetPickerTestTag(WIDGET_PREVIEW_TEST_TAG)
-                    },
+                Modifier.fillMaxSize().clearAndSetSemantics {
+                    traversalIndex = index.toFloat()
+                    testTag = buildWidgetPickerTestTag(WIDGET_PREVIEW_TEST_TAG)
+                },
         ) {
             WidgetPreview(
                 id = widgetItem.id,
                 sizeInfo = widgetItem.sizeInfo,
                 preview = widgetPreview,
-                appwidgetInfo = widgetItem.appWidgetProviderInfo,
+                widgetInfo = widgetItem.widgetInfo,
                 showDragShadow = showDragShadow,
                 onWidgetInteraction = onWidgetInteraction,
-                onAddButtonToggle = onAddButtonToggle
+                onAddButtonToggle = onAddButtonToggle,
             )
         }
     }
@@ -211,7 +210,7 @@
     addButtonWidgetId: WidgetId?,
     appIcons: Map<WidgetAppId, WidgetAppIcon>,
     onWidgetInteraction: (WidgetInteractionInfo) -> Unit,
-    onAddButtonToggle: (WidgetId) -> Unit
+    onAddButtonToggle: (WidgetId) -> Unit,
 ) {
     widgets.forEachIndexed { index, widgetItem ->
         val appId = widgetItem.appId
@@ -376,8 +375,8 @@
         // Move to next row
         yPosition +=
             measuredRow.tallestPreviewHeight +
-                    measuredRow.tallestDetailsHeight +
-                    rowVerticalSpacingPx
+                measuredRow.tallestDetailsHeight +
+                rowVerticalSpacingPx
     }
 }
 
diff --git a/modules/widgetpicker/tests/multivalentScreenshotTests/src/com/android/launcher3/widgetpicker/ui/components/WidgetsGridTestSamples.kt b/modules/widgetpicker/tests/multivalentScreenshotTests/src/com/android/launcher3/widgetpicker/ui/components/WidgetsGridTestSamples.kt
index f86e0ab..29a15ca 100644
--- a/modules/widgetpicker/tests/multivalentScreenshotTests/src/com/android/launcher3/widgetpicker/ui/components/WidgetsGridTestSamples.kt
+++ b/modules/widgetpicker/tests/multivalentScreenshotTests/src/com/android/launcher3/widgetpicker/ui/components/WidgetsGridTestSamples.kt
@@ -30,6 +30,7 @@
 import com.android.launcher3.widgetpicker.shared.model.PickableWidget
 import com.android.launcher3.widgetpicker.shared.model.WidgetAppId
 import com.android.launcher3.widgetpicker.shared.model.WidgetId
+import com.android.launcher3.widgetpicker.shared.model.WidgetInfo
 import com.android.launcher3.widgetpicker.shared.model.WidgetPreview
 import com.android.launcher3.widgetpicker.shared.model.WidgetSizeInfo
 import com.android.launcher3.widgetpicker.tests.R
@@ -253,7 +254,7 @@
                     containerWidthPx = cellWidth,
                     containerHeightPx = cellHeight,
                 ),
-            appWidgetProviderInfo = newAppWidgetInfo("OneByOneProvider"),
+            widgetInfo = WidgetInfo.AppWidgetInfo(newAppWidgetInfo("OneByOneProvider")),
         )
 
     private fun twoByTwo(cellWidth: Int, cellHeight: Int) =
@@ -262,7 +263,7 @@
             appId = TEST_WIDGET_APP_ID,
             label = "Two by Two",
             description = null,
-            appWidgetProviderInfo = newAppWidgetInfo("TwoByTwoProvider"),
+            widgetInfo = WidgetInfo.AppWidgetInfo(newAppWidgetInfo("TwoByTwoProvider")),
             sizeInfo =
                 WidgetSizeInfo(
                     spanX = 2,
@@ -283,7 +284,7 @@
             appId = TEST_WIDGET_APP_ID,
             label = "Three by two",
             description = null,
-            appWidgetProviderInfo = newAppWidgetInfo("threeByTwoProvider"),
+            widgetInfo = WidgetInfo.AppWidgetInfo(newAppWidgetInfo("threeByTwoProvider")),
             sizeInfo =
                 WidgetSizeInfo(
                     spanX = 3,
@@ -304,7 +305,7 @@
             appId = TEST_WIDGET_APP_ID,
             label = "Four by two",
             description = null,
-            appWidgetProviderInfo = newAppWidgetInfo("FourByTwoProvider"),
+            widgetInfo = WidgetInfo.AppWidgetInfo(newAppWidgetInfo("FourByTwoProvider")),
             sizeInfo =
                 WidgetSizeInfo(
                     spanX = 4,
diff --git a/modules/widgetpicker/tests/multivalentTests/src/com/android/launcher3/widgetpicker/TestUtils.kt b/modules/widgetpicker/tests/multivalentTests/src/com/android/launcher3/widgetpicker/TestUtils.kt
index d656701..890191b 100644
--- a/modules/widgetpicker/tests/multivalentTests/src/com/android/launcher3/widgetpicker/TestUtils.kt
+++ b/modules/widgetpicker/tests/multivalentTests/src/com/android/launcher3/widgetpicker/TestUtils.kt
@@ -27,6 +27,7 @@
 import com.android.launcher3.widgetpicker.shared.model.WidgetApp
 import com.android.launcher3.widgetpicker.shared.model.WidgetAppId
 import com.android.launcher3.widgetpicker.shared.model.WidgetId
+import com.android.launcher3.widgetpicker.shared.model.WidgetInfo
 import com.android.launcher3.widgetpicker.shared.model.WidgetPreview
 import com.android.launcher3.widgetpicker.shared.model.WidgetSizeInfo
 import com.android.launcher3.widgetpicker.shared.model.WidgetUserProfile
@@ -118,10 +119,13 @@
             appId = finalWidgetAppId,
             label = providerClassName,
             description = null,
-            appWidgetProviderInfo = AppWidgetProviderInfo().apply {
-                widgetCategory = category
-                provider = ComponentName.createRelative(PACKAGE_NAME, providerClassName)
-            },
+            widgetInfo =
+                WidgetInfo.AppWidgetInfo(
+                    AppWidgetProviderInfo().apply {
+                        widgetCategory = category
+                        provider = ComponentName.createRelative(PACKAGE_NAME, providerClassName)
+                    }
+                ),
             sizeInfo =
                 WidgetSizeInfo(
                     spanX = 2,
diff --git a/modules/widgetpicker/tests/multivalentTests/src/com/android/launcher3/widgetpicker/ui/components/WidgetInteractionsTest.kt b/modules/widgetpicker/tests/multivalentTests/src/com/android/launcher3/widgetpicker/ui/components/WidgetInteractionsTest.kt
index 6e2fb01..83991fa 100644
--- a/modules/widgetpicker/tests/multivalentTests/src/com/android/launcher3/widgetpicker/ui/components/WidgetInteractionsTest.kt
+++ b/modules/widgetpicker/tests/multivalentTests/src/com/android/launcher3/widgetpicker/ui/components/WidgetInteractionsTest.kt
@@ -53,11 +53,9 @@
 @RunWith(AndroidJUnit4::class)
 @AllowedDevices(allowed = [DeviceProduct.CF_PHONE])
 class WidgetInteractionsTest {
-    @get:Rule
-    val limitDevicesRule = LimitDevicesRule()
+    @get:Rule val limitDevicesRule = LimitDevicesRule()
 
-    @get:Rule
-    val composeTestRule = createAndroidComposeRule<ComponentActivity>()
+    @get:Rule val composeTestRule = createAndroidComposeRule<ComponentActivity>()
 
     @Test
     fun tapPreview_andClickAdd() {
@@ -66,7 +64,8 @@
         composeTestRule.waitForIdle()
 
         // tap on preview for widget 1
-        composeTestRule.onAllNodesWithTag(PREVIEW_TEST_TAG)
+        composeTestRule
+            .onAllNodesWithTag(PREVIEW_TEST_TAG)
             .assertCountEquals(2)
             .onFirst()
             .performClick()
@@ -74,18 +73,19 @@
         composeTestRule.waitForIdle()
         composeTestRule.onNodeWithText(WIDGET_ONE.label).isNotDisplayed() // label text not shown
         composeTestRule.onAllNodesWithText(ADD_BUTTON_TEXT).assertCountEquals(1)
-        composeTestRule.onNodeWithContentDescription(WIDGET_ONE_ADD_BUTTON_CONTENT_DESC)
+        composeTestRule
+            .onNodeWithContentDescription(WIDGET_ONE_ADD_BUTTON_CONTENT_DESC)
             .assertExists()
             .performClick()
 
         composeTestRule.waitForIdle()
 
         // widget interaction callback invoked and correct provider info returned.
-        composeTestRule.onNodeWithText(WIDGET_ONE.appWidgetProviderInfo.provider.toString())
-            .assertExists()
+        composeTestRule.onNodeWithText(WIDGET_ONE.widgetInfo.toString()).assertExists()
 
         // tap again on preview for widget 1
-        composeTestRule.onAllNodesWithTag(PREVIEW_TEST_TAG)
+        composeTestRule
+            .onAllNodesWithTag(PREVIEW_TEST_TAG)
             .assertCountEquals(2)
             .onFirst()
             .performClick()
@@ -103,7 +103,8 @@
         composeTestRule.waitForIdle()
 
         // tap on preview for widget 1
-        composeTestRule.onAllNodesWithTag(PREVIEW_TEST_TAG)
+        composeTestRule
+            .onAllNodesWithTag(PREVIEW_TEST_TAG)
             .assertCountEquals(2)
             .onFirst()
             .performClick()
@@ -114,11 +115,13 @@
         composeTestRule.onNodeWithText(WIDGET_ONE.label).isNotDisplayed()
         composeTestRule.onNodeWithText(WIDGET_TWO.label).isNotDisplayed()
         composeTestRule.onAllNodesWithText(ADD_BUTTON_TEXT).assertCountEquals(1)
-        composeTestRule.onNodeWithContentDescription(WIDGET_ONE_ADD_BUTTON_CONTENT_DESC)
+        composeTestRule
+            .onNodeWithContentDescription(WIDGET_ONE_ADD_BUTTON_CONTENT_DESC)
             .assertExists()
 
         // tap on preview for widget 2
-        composeTestRule.onAllNodesWithTag(PREVIEW_TEST_TAG)
+        composeTestRule
+            .onAllNodesWithTag(PREVIEW_TEST_TAG)
             .assertCountEquals(2)
             .onLast()
             .performClick()
@@ -129,11 +132,11 @@
         composeTestRule.onNodeWithText(WIDGET_ONE.label).isDisplayed()
         composeTestRule.onNodeWithText(WIDGET_TWO.label).isNotDisplayed()
         composeTestRule.onAllNodesWithText(ADD_BUTTON_TEXT).assertCountEquals(1)
-        composeTestRule.onNodeWithContentDescription(WIDGET_TWO_ADD_BUTTON_CONTENT_DESC)
+        composeTestRule
+            .onNodeWithContentDescription(WIDGET_TWO_ADD_BUTTON_CONTENT_DESC)
             .assertExists()
     }
 
-
     @Composable
     fun TapToAddTestComposable() {
         var provider by remember { mutableStateOf("invalid") }
@@ -149,7 +152,7 @@
                 showDragShadow = false,
                 onWidgetInteraction = { widgetInteractionInfo ->
                     if (widgetInteractionInfo is WidgetInteractionInfo.WidgetAddInfo) {
-                        provider = widgetInteractionInfo.providerInfo.provider.toString()
+                        provider = widgetInteractionInfo.widgetInfo.toString()
                     }
                 },
             )
@@ -160,16 +163,18 @@
         private val WIDGET_ONE = PERSONAL_TEST_APPS[0].widgets[0]
         private val WIDGET_TWO = PERSONAL_TEST_APPS[1].widgets[0]
 
-        private val TEST_WIDGET_GROUP = WidgetSizeGroup(
-            previewContainerHeightPx = 200,
-            previewContainerWidthPx = 200,
-            widgets = listOf(WIDGET_ONE, WIDGET_TWO)
-        )
+        private val TEST_WIDGET_GROUP =
+            WidgetSizeGroup(
+                previewContainerHeightPx = 200,
+                previewContainerWidthPx = 200,
+                widgets = listOf(WIDGET_ONE, WIDGET_TWO),
+            )
 
-        private val PREVIEWS = mapOf(
-            WIDGET_ONE.id to TestUtils.createBitmapPreview(),
-            WIDGET_TWO.id to TestUtils.createBitmapPreview()
-        )
+        private val PREVIEWS =
+            mapOf(
+                WIDGET_ONE.id to TestUtils.createBitmapPreview(),
+                WIDGET_TWO.id to TestUtils.createBitmapPreview(),
+            )
 
         private val PREVIEW_TEST_TAG = buildWidgetPickerTestTag("widget_preview")
         private const val ADD_BUTTON_TEXT = "Add"
diff --git a/res/values/config.xml b/res/values/config.xml
index 05f489c..674b093 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -139,13 +139,6 @@
 
     <string-array name="filtered_components" ></string-array>
     <string-array name="default_featured_widget_apps" translatable="false">
-        <item>com.google.android.calendar</item>
-        <item>com.google.android.deskclock</item>
-        <item>com.google.android.apps.maps</item>
-        <item>com.google.android.contacts</item>
-        <item>com.google.android.apps.chromecast.app</item>
-        <item>com.google.android.gm</item>
-        <item>com.google.android.videos</item>
     </string-array>
 
     <!-- Swipe back to home related -->
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index 89c6351..8a76f85 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -21,6 +21,7 @@
 
 import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
+import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
 import static com.android.launcher3.icons.FastBitmapDrawable.getDisabledColorFilter;
 import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
 
@@ -635,7 +636,8 @@
                 // When widgets are dropped from another window, we don't want to remove the
                 // dragView on resume of launcher.
                 if (Flags.enableWidgetPickerRefactor()
-                        && ((DragView<?>) child).mItemType != ITEM_TYPE_APPWIDGET) {
+                        && ((DragView<?>) child).mItemType != ITEM_TYPE_APPWIDGET
+                        && ((DragView<?>) child).mItemType != ITEM_TYPE_DEEP_SHORTCUT) {
                     dragLayer.removeView(child);
                 }
             }
diff --git a/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java b/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java
index 409174e..235a46c 100644
--- a/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java
+++ b/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java
@@ -134,7 +134,7 @@
     @TargetApi(26)
     public static class ShortcutConfigActivityInfoVO extends ShortcutConfigActivityInfo {
 
-        private final LauncherActivityInfo mInfo;
+        public final LauncherActivityInfo mInfo;
 
         public ShortcutConfigActivityInfoVO(LauncherActivityInfo info) {
             super(info.getComponentName(), info.getUser(),
diff --git a/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java b/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
index 55404d6..48f75c7 100644
--- a/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
+++ b/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
@@ -51,7 +51,6 @@
 import com.android.launcher3.util.CancellableTask;
 import com.android.launcher3.util.Executors;
 import com.android.launcher3.util.LooperExecutor;
-import com.android.launcher3.views.ActivityContext;
 import com.android.launcher3.widget.util.WidgetSizes;
 
 import java.util.concurrent.ExecutionException;
@@ -272,8 +271,7 @@
 
     private Bitmap generateShortcutPreview(
             ShortcutConfigActivityInfo info, int maxWidth, int maxHeight) {
-        int iconSize = ActivityContext.lookupContext(
-                mContext).getDeviceProfile().getAllAppsProfile().getIconSizePx();
+        int iconSize = mDeviceProfile.getAllAppsProfile().getIconSizePx();
         int padding = mContext.getResources()
                 .getDimensionPixelSize(R.dimen.widget_preview_shortcut_padding);