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.annotation.Nullable; 20 import android.content.ComponentName; 21 import android.content.Context; 22 import android.content.pm.ActivityInfo; 23 import android.content.pm.LauncherApps; 24 import android.content.pm.PackageManager; 25 import android.content.pm.ShortcutInfo; 26 import android.graphics.Bitmap; 27 import android.graphics.drawable.BitmapDrawable; 28 import android.graphics.drawable.Drawable; 29 import android.graphics.drawable.Icon; 30 import android.os.Trace; 31 import android.util.Log; 32 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; 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 drawable = loadIconPlaceholder(); 74 } 75 } catch (Exception e) { 76 Log.e( 77 TAG, 78 "Failed to load shortcut icon for " 79 + mTargetInfo.getChooserTargetComponentName(), 80 e); 81 drawable = loadIconPlaceholder(); 82 } finally { 83 Trace.endSection(); 84 } 85 return drawable; 86 } 87 88 @WorkerThread getChooserTargetIconDrawable( Context context, @Nullable Icon icon, ComponentName targetComponentName, @Nullable ShortcutInfo shortcutInfo)89 private Drawable getChooserTargetIconDrawable( 90 Context context, 91 @Nullable Icon icon, 92 ComponentName targetComponentName, 93 @Nullable ShortcutInfo shortcutInfo) { 94 Drawable directShareIcon = null; 95 96 // First get the target drawable and associated activity info 97 if (icon != null) { 98 directShareIcon = icon.loadDrawable(context); 99 } else if (shortcutInfo != null) { 100 LauncherApps launcherApps = context.getSystemService(LauncherApps.class); 101 if (launcherApps != null) { 102 directShareIcon = launcherApps.getShortcutIconDrawable(shortcutInfo, 0); 103 } 104 } 105 106 if (directShareIcon == null) { 107 return null; 108 } 109 110 ActivityInfo info = null; 111 try { 112 info = context.getPackageManager().getActivityInfo(targetComponentName, 0); 113 } catch (PackageManager.NameNotFoundException error) { 114 Log.e(TAG, "Could not find activity associated with ChooserTarget"); 115 } 116 117 if (info == null) { 118 return null; 119 } 120 121 // Now fetch app icon and raster with no badging even in work profile 122 Bitmap appIcon = mPresentationFactory.makePresentationGetter(info).getIconBitmap(null); 123 124 // Raster target drawable with appIcon as a badge 125 SimpleIconFactory sif = SimpleIconFactory.obtain(context); 126 Bitmap directShareBadgedIcon = sif.createAppBadgedIconBitmap(directShareIcon, appIcon); 127 sif.recycle(); 128 129 return new BitmapDrawable(context.getResources(), directShareBadgedIcon); 130 } 131 } 132