1 /* 2 * Copyright (C) 2023 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.intentresolver.icons; 18 19 import android.content.ComponentName; 20 import android.content.Context; 21 import android.content.pm.ActivityInfo; 22 import android.content.pm.LauncherApps; 23 import android.content.pm.PackageManager; 24 import android.content.pm.ShortcutInfo; 25 import android.graphics.Bitmap; 26 import android.graphics.drawable.BitmapDrawable; 27 import android.graphics.drawable.Drawable; 28 import android.graphics.drawable.Icon; 29 import android.os.Trace; 30 import android.util.Log; 31 32 import androidx.annotation.Nullable; 33 import androidx.annotation.WorkerThread; 34 35 import com.android.intentresolver.SimpleIconFactory; 36 import com.android.intentresolver.TargetPresentationGetter; 37 import com.android.intentresolver.chooser.SelectableTargetInfo; 38 import com.android.intentresolver.util.UriFilters; 39 40 import java.util.function.Consumer; 41 42 /** 43 * Loads direct share targets icons. 44 */ 45 class LoadDirectShareIconTask extends BaseLoadIconTask { 46 private static final String TAG = "DirectShareIconTask"; 47 private final SelectableTargetInfo mTargetInfo; 48 LoadDirectShareIconTask( Context context, SelectableTargetInfo targetInfo, TargetPresentationGetter.Factory presentationFactory, Consumer<Drawable> callback)49 LoadDirectShareIconTask( 50 Context context, 51 SelectableTargetInfo targetInfo, 52 TargetPresentationGetter.Factory presentationFactory, 53 Consumer<Drawable> callback) { 54 super(context, presentationFactory, callback); 55 mTargetInfo = targetInfo; 56 } 57 58 @Override doInBackground(Void... voids)59 protected Drawable doInBackground(Void... voids) { 60 Drawable drawable = null; 61 Trace.beginSection("shortcut-icon"); 62 try { 63 final Icon icon = mTargetInfo.getChooserTargetIcon(); 64 if (icon == null || UriFilters.hasValidIcon(icon)) { 65 drawable = getChooserTargetIconDrawable( 66 mContext, 67 icon, 68 mTargetInfo.getChooserTargetComponentName(), 69 mTargetInfo.getDirectShareShortcutInfo()); 70 } else { 71 Log.e(TAG, "Failed to load shortcut icon for " 72 + mTargetInfo.getChooserTargetComponentName() + "; no access"); 73 } 74 if (drawable == null) { 75 drawable = loadIconPlaceholder(); 76 } 77 } catch (Exception e) { 78 Log.e( 79 TAG, 80 "Failed to load shortcut icon for " 81 + mTargetInfo.getChooserTargetComponentName(), 82 e); 83 drawable = loadIconPlaceholder(); 84 } finally { 85 Trace.endSection(); 86 } 87 return drawable; 88 } 89 90 @WorkerThread 91 @Nullable getChooserTargetIconDrawable( Context context, @Nullable Icon icon, ComponentName targetComponentName, @Nullable ShortcutInfo shortcutInfo)92 private Drawable getChooserTargetIconDrawable( 93 Context context, 94 @Nullable Icon icon, 95 ComponentName targetComponentName, 96 @Nullable ShortcutInfo shortcutInfo) { 97 Drawable directShareIcon = null; 98 99 // First get the target drawable and associated activity info 100 if (icon != null) { 101 directShareIcon = icon.loadDrawable(context); 102 } else if (shortcutInfo != null) { 103 LauncherApps launcherApps = context.getSystemService(LauncherApps.class); 104 if (launcherApps != null) { 105 directShareIcon = launcherApps.getShortcutIconDrawable(shortcutInfo, 0); 106 } 107 } 108 109 if (directShareIcon == null) { 110 return null; 111 } 112 113 ActivityInfo info = null; 114 try { 115 info = context.getPackageManager().getActivityInfo(targetComponentName, 0); 116 } catch (PackageManager.NameNotFoundException error) { 117 Log.e(TAG, "Could not find activity associated with ChooserTarget"); 118 } 119 120 if (info == null) { 121 return null; 122 } 123 124 // Now fetch app icon and raster with no badging even in work profile 125 Bitmap appIcon = mPresentationFactory.makePresentationGetter(info).getIconBitmap(null); 126 127 // Raster target drawable with appIcon as a badge 128 SimpleIconFactory sif = SimpleIconFactory.obtain(context); 129 Bitmap directShareBadgedIcon = sif.createAppBadgedIconBitmap(directShareIcon, appIcon); 130 sif.recycle(); 131 132 return new BitmapDrawable(context.getResources(), directShareBadgedIcon); 133 } 134 } 135