2025-05-28 06:48:34 -07:00
|
|
|
/*
|
|
|
|
|
* 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.datasource
|
|
|
|
|
|
|
|
|
|
import android.content.Context
|
|
|
|
|
import com.android.launcher3.InvariantDeviceProfile
|
|
|
|
|
import com.android.launcher3.R
|
|
|
|
|
import com.android.launcher3.dagger.ApplicationContext
|
|
|
|
|
import com.android.launcher3.dagger.LauncherAppSingleton
|
|
|
|
|
import com.android.launcher3.widget.picker.util.WidgetPreviewContainerSize
|
|
|
|
|
import com.android.launcher3.widgetpicker.shared.model.PickableWidget
|
|
|
|
|
import com.android.launcher3.widgetpicker.shared.model.WidgetApp
|
2025-06-08 17:29:33 +00:00
|
|
|
import com.android.launcher3.widgetpicker.shared.model.isAppWidget
|
2025-05-28 06:48:34 -07:00
|
|
|
import java.util.Arrays
|
|
|
|
|
import java.util.stream.Collectors
|
|
|
|
|
import javax.inject.Inject
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* An implementation of [FeaturedWidgetsDataSource] that provides featured widgets based on a static
|
|
|
|
|
* configuration from resources and pre-defined size templates.
|
2025-06-08 17:29:33 +00:00
|
|
|
*
|
|
|
|
|
* Only appwidgets; no shortcuts
|
2025-05-28 06:48:34 -07:00
|
|
|
*/
|
|
|
|
|
@LauncherAppSingleton
|
2025-06-08 17:29:33 +00:00
|
|
|
class ConfigResourceFeaturedWidgetsDataSource
|
|
|
|
|
@Inject
|
|
|
|
|
constructor(
|
2025-05-28 06:48:34 -07:00
|
|
|
@ApplicationContext private val appContext: Context,
|
2025-06-08 17:29:33 +00:00
|
|
|
private val idp: InvariantDeviceProfile,
|
2025-05-28 06:48:34 -07:00
|
|
|
) : 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()) {
|
2025-06-08 17:29:33 +00:00
|
|
|
eligiblePackages =
|
|
|
|
|
Arrays.stream(
|
|
|
|
|
appContext.resources.getStringArray(R.array.default_featured_widget_apps)
|
|
|
|
|
)
|
|
|
|
|
.collect(Collectors.toSet())
|
2025-05-28 06:48:34 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override suspend fun getFeaturedWidgets(widgetApps: List<WidgetApp>): List<PickableWidget> {
|
2025-06-08 17:29:33 +00:00
|
|
|
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,
|
|
|
|
|
)
|
|
|
|
|
}
|
2025-05-28 06:48:34 -07:00
|
|
|
|
|
|
|
|
val selected: MutableList<PickableWidget> = mutableListOf()
|
|
|
|
|
val usedAppIds: MutableSet<String> = mutableSetOf()
|
|
|
|
|
|
2025-06-08 17:29:33 +00:00
|
|
|
val sizesToPick =
|
|
|
|
|
WidgetPreviewContainerSize.pickTemplateForFeaturedWidgets(
|
|
|
|
|
idp.getDeviceProfile(appContext)
|
|
|
|
|
)
|
2025-05-28 06:48:34 -07:00
|
|
|
for (sizeToPick in sizesToPick) {
|
|
|
|
|
widgetsByContainerSize[sizeToPick]?.shuffled()?.let { items ->
|
|
|
|
|
for (item in items) {
|
2025-06-08 17:29:33 +00:00
|
|
|
if (
|
|
|
|
|
item.widgetInfo.isAppWidget() &&
|
|
|
|
|
!usedAppIds.contains(item.appId.packageName)
|
|
|
|
|
) {
|
2025-05-28 06:48:34 -07:00
|
|
|
selected.add(item)
|
|
|
|
|
usedAppIds.add(item.appId.packageName)
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return selected
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun cleanup() {
|
|
|
|
|
eligiblePackages = emptySet()
|
|
|
|
|
}
|
|
|
|
|
}
|