From a4ffc73d92457c96af6b44b4b0fd656d02fd42e5 Mon Sep 17 00:00:00 2001 From: Shamali Patwa Date: Thu, 22 May 2025 16:03:16 -0700 Subject: [PATCH] Updates to repository interfaces & data types for widget picker - I think the previews / featured / search all could be part of widgets repository. Internally, it will use separate datasource to prepare the respective data - but as a repository, they all are probably just a widgets repo. - Includes minor changes to data types as well to prepare for upcoming changes. Bug: 408283627 Flag: EXEMPT independent module Test: Not applicable - interface changes Change-Id: I765c11318a655603becdf2cab081f0fcf777da1a --- modules/widgetpicker/Android.bp | 6 +- ...idgetPickerSingleton.kt => Annotations.kt} | 7 +++ .../repository/WidgetAppIconsRepository.kt | 9 +++ .../WidgetRecommendationsRepository.kt | 25 -------- .../data/repository/WidgetUsersRepository.kt | 16 ++++- .../data/repository/WidgetsRepository.kt | 27 ++++++++- .../shared/model/PickableWidget.kt | 7 ++- .../model/WidgetApp.kt} | 25 ++++---- .../shared/model/WidgetHostInfo.kt | 59 +++++++++++++++++++ .../shared/model/WidgetUserProfiles.kt | 6 +- 10 files changed, 141 insertions(+), 46 deletions(-) rename modules/widgetpicker/src/com/android/launcher3/widgetpicker/{WidgetPickerSingleton.kt => Annotations.kt} (80%) delete mode 100644 modules/widgetpicker/src/com/android/launcher3/widgetpicker/data/repository/WidgetRecommendationsRepository.kt rename modules/widgetpicker/src/com/android/launcher3/widgetpicker/{data/repository/WidgetPreviewRepository.kt => shared/model/WidgetApp.kt} (55%) create mode 100644 modules/widgetpicker/src/com/android/launcher3/widgetpicker/shared/model/WidgetHostInfo.kt diff --git a/modules/widgetpicker/Android.bp b/modules/widgetpicker/Android.bp index 6d81149e1c..301be44f0d 100644 --- a/modules/widgetpicker/Android.bp +++ b/modules/widgetpicker/Android.bp @@ -22,7 +22,7 @@ android_library { sdk_version: "current", min_sdk_version: min_launcher3_sdk_version, srcs: [ - "src/com/android/launcher3/widgetpicker/WidgetPickerSingleton.kt", + "src/com/android/launcher3/widgetpicker/Annotations.kt", ], static_libs: [ @@ -52,11 +52,13 @@ android_library { min_sdk_version: min_launcher3_sdk_version, srcs: [ "src/com/android/launcher3/widgetpicker/shared/model/PickableWidget.kt", + "src/com/android/launcher3/widgetpicker/shared/model/WidgetApp.kt", "src/com/android/launcher3/widgetpicker/shared/model/WidgetAppIcon.kt", "src/com/android/launcher3/widgetpicker/shared/model/WidgetAppId.kt", "src/com/android/launcher3/widgetpicker/shared/model/WidgetId.kt", "src/com/android/launcher3/widgetpicker/shared/model/WidgetPreview.kt", "src/com/android/launcher3/widgetpicker/shared/model/WidgetUserProfiles.kt", + "src/com/android/launcher3/widgetpicker/shared/model/WidgetHostInfo.kt", ], static_libs: [ "androidx.core_core-ktx", @@ -70,8 +72,6 @@ android_library { min_sdk_version: min_launcher3_sdk_version, srcs: [ "src/com/android/launcher3/widgetpicker/data/repository/WidgetAppIconsRepository.kt", - "src/com/android/launcher3/widgetpicker/data/repository/WidgetPreviewRepository.kt", - "src/com/android/launcher3/widgetpicker/data/repository/WidgetRecommendationsRepository.kt", "src/com/android/launcher3/widgetpicker/data/repository/WidgetsRepository.kt", "src/com/android/launcher3/widgetpicker/data/repository/WidgetUsersRepository.kt", ], diff --git a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/WidgetPickerSingleton.kt b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/Annotations.kt similarity index 80% rename from modules/widgetpicker/src/com/android/launcher3/widgetpicker/WidgetPickerSingleton.kt rename to modules/widgetpicker/src/com/android/launcher3/widgetpicker/Annotations.kt index ce6e7857a6..276ffefaf0 100644 --- a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/WidgetPickerSingleton.kt +++ b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/Annotations.kt @@ -16,6 +16,7 @@ package com.android.launcher3.widgetpicker +import javax.inject.Qualifier import javax.inject.Scope /** Scope annotation for singleton items within the widget picker. */ @@ -23,3 +24,9 @@ import javax.inject.Scope @Retention(AnnotationRetention.RUNTIME) @Scope annotation class WidgetPickerSingleton + +/** Qualifier annotation for information about the widget host. */ +@Qualifier +@MustBeDocumented +@Retention(AnnotationRetention.RUNTIME) +annotation class WidgetPickerHostInfo diff --git a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/data/repository/WidgetAppIconsRepository.kt b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/data/repository/WidgetAppIconsRepository.kt index 68fd7cbe7b..bbd5f89bfd 100644 --- a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/data/repository/WidgetAppIconsRepository.kt +++ b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/data/repository/WidgetAppIconsRepository.kt @@ -22,9 +22,18 @@ import kotlinx.coroutines.flow.Flow /** A repository that provides app icons for the widget picker. */ interface WidgetAppIconsRepository { + /** + * A hook to setup the repository so clients can observe the widgets available on device. + * This serves as a place to start listening to the backing caches / data sources. + */ + fun initialize() + /** * Loads and returns app icon (may initially return a low res icon, followed by a high res once * available). */ fun getAppIcon(widgetAppId: WidgetAppId): Flow + + /** Clean up any external listeners or state (if necessary). */ + fun cleanUp() } diff --git a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/data/repository/WidgetRecommendationsRepository.kt b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/data/repository/WidgetRecommendationsRepository.kt deleted file mode 100644 index 7e5403f104..0000000000 --- a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/data/repository/WidgetRecommendationsRepository.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2025 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.launcher3.widgetpicker.data.repository - -import com.android.launcher3.widgetpicker.shared.model.WidgetId - -/** A repository of widgets that can be recommended to the users in widget picker. */ -interface WidgetRecommendationsRepository { - /** Returns a list of widgets that can be recommended to the users in the widget picker. */ - suspend fun getRecommendations(): List -} diff --git a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/data/repository/WidgetUsersRepository.kt b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/data/repository/WidgetUsersRepository.kt index e81c3abc16..d28b11c3dd 100644 --- a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/data/repository/WidgetUsersRepository.kt +++ b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/data/repository/WidgetUsersRepository.kt @@ -16,7 +16,7 @@ package com.android.launcher3.widgetpicker.data.repository -import com.android.launcher3.widgetpicker.shared.model.WidgetUserProfileType +import android.os.UserHandle import com.android.launcher3.widgetpicker.shared.model.WidgetUserProfiles import kotlinx.coroutines.flow.Flow @@ -25,6 +25,18 @@ import kotlinx.coroutines.flow.Flow * the widget picker. */ interface WidgetUsersRepository { + /** + * A hook to setup the repository so clients can observe the widgets available on device. + * This serves as a place to start listening to the backing caches / data sources. + */ + fun initialize() + /** Get and listen to the changes in available user profiles. */ - fun observeUsers(types: List): Flow + fun observeUserProfiles(): Flow + + /** Indicates if a user is a work profile user. */ + fun getWorkProfileUser(): UserHandle? + + /** Clean up any external listeners or state (if necessary). */ + fun cleanUp() } diff --git a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/data/repository/WidgetsRepository.kt b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/data/repository/WidgetsRepository.kt index 5f9d8a9872..a28a776380 100644 --- a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/data/repository/WidgetsRepository.kt +++ b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/data/repository/WidgetsRepository.kt @@ -17,11 +17,34 @@ package com.android.launcher3.widgetpicker.data.repository import com.android.launcher3.widgetpicker.shared.model.PickableWidget +import com.android.launcher3.widgetpicker.shared.model.WidgetApp +import com.android.launcher3.widgetpicker.shared.model.WidgetId +import com.android.launcher3.widgetpicker.shared.model.WidgetPreview import kotlinx.coroutines.flow.Flow /** A repository of widgets available on the device from various apps */ interface WidgetsRepository { + /** + * A hook to setup the repository so clients can observe the widgets available on device. + * This serves as a place to start listening to the backing caches / data sources. + */ + fun initialize() - /** Observe widgets available on the device. */ - fun observeWidgets(): Flow> + /** Observe widgets available on the device from different apps. */ + fun observeWidgets(): Flow> + + /** Loads a preview for an app widget. Returns a placeholder preview if the widget is not found. */ + suspend fun getWidgetPreview(id: WidgetId): WidgetPreview + + /** Get widgets that can be featured in widget picker. */ + fun getFeaturedWidgets(): Flow> + + /** + * Search widgets and their apps that match the given plain text [query] string typed by the + * user. Matches the widget's label, description and app's title (case-insensitive). + */ + suspend fun searchWidgets(query: String): List + + /** Clean up any external listeners or state (if necessary). */ + fun cleanUp() } 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 fb0e2863c4..d37154a4b4 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 @@ -39,7 +39,12 @@ data class PickableWidget( val description: CharSequence?, val appWidgetProviderInfo: AppWidgetProviderInfo, 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})" +} /** * Sizing information for a specific widget shown in a grid. diff --git a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/data/repository/WidgetPreviewRepository.kt b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/shared/model/WidgetApp.kt similarity index 55% rename from modules/widgetpicker/src/com/android/launcher3/widgetpicker/data/repository/WidgetPreviewRepository.kt rename to modules/widgetpicker/src/com/android/launcher3/widgetpicker/shared/model/WidgetApp.kt index 8cb4265b61..b17dfe98e5 100644 --- a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/data/repository/WidgetPreviewRepository.kt +++ b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/shared/model/WidgetApp.kt @@ -1,3 +1,5 @@ +package com.android.launcher3.widgetpicker.shared.model + /* * Copyright (C) 2025 The Android Open Source Project * @@ -14,13 +16,16 @@ * limitations under the License. */ -package com.android.launcher3.widgetpicker.data.repository - -import com.android.launcher3.widgetpicker.shared.model.WidgetId -import com.android.launcher3.widgetpicker.shared.model.WidgetPreview - -/** A repository that provides previews for the widgets to be displayed in the widget picker. */ -interface WidgetPreviewRepository { - /** Returns the preview for a widget represented by given [WidgetId]. */ - suspend fun getPreview(widgetId: WidgetId): WidgetPreview -} +/** + * Represents an app hosting widgets that is shown in widget picker. + * + * @param id a unique identifier for the app + * @param title a user readable title for the app; if null a placeholder text (e.g. "pending..") + * is shown until the title is loaded. + * @param widgets list of widgets available to picker from the app. + */ +data class WidgetApp( + val id: WidgetAppId, + val title: CharSequence?, + val widgets: List, +) 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 new file mode 100644 index 0000000000..6d48e5a67e --- /dev/null +++ b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/shared/model/WidgetHostInfo.kt @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.widgetpicker.shared.model + +import android.os.UserHandle + +/** + * Data class that holds information about the host needs to display the widget picker. + * + * @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. + * @param constraints constraints around which widgets can be shown in the picker. + */ +data class WidgetHostInfo( + val title: String? = null, + val description: String? = null, + val constraints: List = emptyList(), +) + +/** Various constraints for the widget host. */ +sealed class HostConstraint { + /** + * A constraint to apply on `widgetCategory` when deciding whether to show a widget in the + * widget picker. + * + * @param categoryInclusionMask mask that includes widgets matching the given widget category + * mask e.g. HOME_SCREEN or KEYGUARD; 0 implies no mask + * @param categoryExclusionMask mask that excludes widgets matching the mask e.g. + * NOT_KEYGUARD.inv(); 0 implies no mask + */ + data class HostCategoryConstraint( + val categoryInclusionMask: Int, + val categoryExclusionMask: Int, + ) : HostConstraint() + + /** + * A constraint to apply on `user` associated with widgets shown in widget picker. + * + * @param userFilters user profiles for which widgets list should be shown as empty. e.g. for + * lockscreen widgets, based on an admin setting, the host may filter out work widgets. In + * such case, the profile tab shows a generic no widgets available message. + */ + data class HostUserConstraint(val userFilters: List) : HostConstraint() +} diff --git a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/shared/model/WidgetUserProfiles.kt b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/shared/model/WidgetUserProfiles.kt index 472fb6e58f..cf15959fb2 100644 --- a/modules/widgetpicker/src/com/android/launcher3/widgetpicker/shared/model/WidgetUserProfiles.kt +++ b/modules/widgetpicker/src/com/android/launcher3/widgetpicker/shared/model/WidgetUserProfiles.kt @@ -20,7 +20,7 @@ package com.android.launcher3.widgetpicker.shared.model * Holds data about all the available user profiles on device that are supported in the widget * picker. */ -data class WidgetUserProfiles(val users: List) +data class WidgetUserProfiles(val personal: WidgetUserProfile, val work: WidgetUserProfile?) /** * Data about a specific user profile that is supported in the widget picker. @@ -36,8 +36,8 @@ data class WidgetUserProfiles(val users: List) data class WidgetUserProfile( val type: WidgetUserProfileType, val label: String, - val paused: Boolean, - val pausedProfileMessage: String, + val paused: Boolean = false, + val pausedProfileMessage: String? = null, ) /** Represents types of user profiles that are supported in the widget picker. */