1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.launcher3.widget.picker; 18 19 import android.content.Context; 20 import android.content.pm.ApplicationInfo; 21 22 import androidx.annotation.Nullable; 23 import androidx.annotation.WorkerThread; 24 25 import com.android.launcher3.R; 26 import com.android.launcher3.model.WidgetItem; 27 import com.android.launcher3.util.PackageManagerHelper; 28 import com.android.launcher3.util.Preconditions; 29 import com.android.launcher3.util.ResourceBasedOverride; 30 31 /** 32 * A {@link ResourceBasedOverride} that categorizes widget recommendations. 33 * 34 * <p>Override the {@code widget_recommendation_category_provider_class} resource to provide your 35 * own implementation. Method {@code getWidgetRecommendationCategory} is called per widget to get 36 * the category.</p> 37 */ 38 public class WidgetRecommendationCategoryProvider implements ResourceBasedOverride { 39 private static final String TAG = "WidgetRecommendationCategoryProvider"; 40 41 /** 42 * Retrieve instance of this object that can be overridden in runtime based on the build 43 * variant of the application. 44 */ newInstance(Context context)45 public static WidgetRecommendationCategoryProvider newInstance(Context context) { 46 Preconditions.assertWorkerThread(); 47 return Overrides.getObject( 48 WidgetRecommendationCategoryProvider.class, context.getApplicationContext(), 49 R.string.widget_recommendation_category_provider_class); 50 } 51 52 /** 53 * Returns a {@link WidgetRecommendationCategory} for the provided widget item that can be used 54 * to display the recommendation grouped by categories. 55 */ 56 @WorkerThread 57 @Nullable getWidgetRecommendationCategory(Context context, WidgetItem item)58 public WidgetRecommendationCategory getWidgetRecommendationCategory(Context context, 59 WidgetItem item) { 60 // This is a default implementation that uses application category to derive the category to 61 // be displayed. The implementation can be overridden in individual launcher customization 62 // via the overridden WidgetRecommendationCategoryProvider resource. 63 64 Preconditions.assertWorkerThread(); 65 try (PackageManagerHelper pmHelper = new PackageManagerHelper(context)) { 66 if (item.widgetInfo != null && item.widgetInfo.getComponent() != null) { 67 ApplicationInfo applicationInfo = pmHelper.getApplicationInfo( 68 item.widgetInfo.getComponent().getPackageName(), item.widgetInfo.getUser(), 69 0 /* flags */); 70 if (applicationInfo != null) { 71 return getCategoryFromApplicationCategory(applicationInfo.category); 72 } 73 } 74 } 75 return null; 76 } 77 78 /** Maps application category to an appropriate displayable category. */ getCategoryFromApplicationCategory( int applicationCategory)79 private static WidgetRecommendationCategory getCategoryFromApplicationCategory( 80 int applicationCategory) { 81 if (applicationCategory == ApplicationInfo.CATEGORY_PRODUCTIVITY) { 82 return new WidgetRecommendationCategory( 83 R.string.productivity_widget_recommendation_category_label, /*order=*/0); 84 } 85 86 if (applicationCategory == ApplicationInfo.CATEGORY_NEWS) { 87 return new WidgetRecommendationCategory( 88 R.string.news_widget_recommendation_category_label, /*order=*/1); 89 } 90 91 if (applicationCategory == ApplicationInfo.CATEGORY_SOCIAL) { 92 return new WidgetRecommendationCategory( 93 R.string.social_widget_recommendation_category_label, 94 /*order=*/3); 95 } 96 97 if (applicationCategory == ApplicationInfo.CATEGORY_AUDIO 98 || applicationCategory == ApplicationInfo.CATEGORY_VIDEO 99 || applicationCategory == ApplicationInfo.CATEGORY_IMAGE) { 100 return new WidgetRecommendationCategory( 101 R.string.entertainment_widget_recommendation_category_label, 102 /*order=*/4); 103 } 104 105 return new WidgetRecommendationCategory( 106 R.string.others_widget_recommendation_category_label, /*order=*/2); 107 } 108 } 109