summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--java/src/com/android/intentresolver/ChooserTargetActionsDialogFragment.java6
-rw-r--r--java/src/com/android/intentresolver/SimpleIconFactory.java15
-rw-r--r--java/src/com/android/intentresolver/TargetPresentationGetter.java53
-rw-r--r--java/src/com/android/intentresolver/icons/DefaultTargetDataLoader.kt12
-rw-r--r--java/src/com/android/intentresolver/icons/LoadDirectShareIconTask.java12
-rw-r--r--java/src/com/android/intentresolver/icons/TargetDataLoaderModule.kt21
-rw-r--r--tests/unit/src/com/android/intentresolver/TargetPresentationGetterTest.kt26
7 files changed, 105 insertions, 40 deletions
diff --git a/java/src/com/android/intentresolver/ChooserTargetActionsDialogFragment.java b/java/src/com/android/intentresolver/ChooserTargetActionsDialogFragment.java
index ff0bda01..8070fc84 100644
--- a/java/src/com/android/intentresolver/ChooserTargetActionsDialogFragment.java
+++ b/java/src/com/android/intentresolver/ChooserTargetActionsDialogFragment.java
@@ -281,7 +281,11 @@ public class ChooserTargetActionsDialogFragment extends DialogFragment
final int iconDpi = am.getLauncherLargeIconDensity();
// Use the matching application icon and label for the title, any TargetInfo will do
- return new TargetPresentationGetter.Factory(getContext(), iconDpi)
+ final Context context = getContext();
+ return new TargetPresentationGetter.Factory(
+ () -> SimpleIconFactory.obtain(context),
+ context.getPackageManager(),
+ iconDpi)
.makePresentationGetter(mTargetInfos.get(0).getResolveInfo());
}
diff --git a/java/src/com/android/intentresolver/SimpleIconFactory.java b/java/src/com/android/intentresolver/SimpleIconFactory.java
index f4871e36..afb7d19e 100644
--- a/java/src/com/android/intentresolver/SimpleIconFactory.java
+++ b/java/src/com/android/intentresolver/SimpleIconFactory.java
@@ -64,7 +64,7 @@ import java.util.Optional;
* possibly badged. It is intended to be used only by Sharesheet for the Q release with custom code.
*/
@Deprecated
-public class SimpleIconFactory {
+public class SimpleIconFactory implements AutoCloseable {
private static final SynchronizedPool<SimpleIconFactory> sPool =
@@ -139,6 +139,11 @@ public class SimpleIconFactory {
"Expected theme to define iconfactoryBadgeSize.");
}
+ @Override
+ public void close() {
+ recycle();
+ }
+
/**
* Recycles the SimpleIconFactory so others may use it.
*
@@ -146,9 +151,11 @@ public class SimpleIconFactory {
*/
@Deprecated
public void recycle() {
- // Return to default background color
- setWrapperBackgroundColor(Color.WHITE);
- sPool.release(this);
+ if (sPoolEnabled) {
+ // Return to default background color
+ setWrapperBackgroundColor(Color.WHITE);
+ sPool.release(this);
+ }
}
/**
diff --git a/java/src/com/android/intentresolver/TargetPresentationGetter.java b/java/src/com/android/intentresolver/TargetPresentationGetter.java
index ac74366e..3a7f807d 100644
--- a/java/src/com/android/intentresolver/TargetPresentationGetter.java
+++ b/java/src/com/android/intentresolver/TargetPresentationGetter.java
@@ -16,7 +16,6 @@
package com.android.intentresolver;
-import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -30,6 +29,8 @@ import android.util.Log;
import androidx.annotation.Nullable;
+import javax.inject.Provider;
+
/**
* Loads the icon and label for the provided ApplicationInfo. Defaults to using the application icon
* and label over any IntentFilter or Activity icon to increase user understanding, with an
@@ -48,22 +49,29 @@ public abstract class TargetPresentationGetter {
/** Helper to build appropriate type-specific {@link TargetPresentationGetter} instances. */
public static class Factory {
- private final Context mContext;
+ private final Provider<SimpleIconFactory> mIconFactoryProvider;
+ private final PackageManager mPackageManager;
private final int mIconDpi;
- public Factory(Context context, int iconDpi) {
- mContext = context;
+ public Factory(
+ Provider<SimpleIconFactory> iconfactoryProvider,
+ PackageManager packageManager,
+ int iconDpi) {
+ mIconFactoryProvider = iconfactoryProvider;
+ mPackageManager = packageManager;
mIconDpi = iconDpi;
}
/** Make a {@link TargetPresentationGetter} for an {@link ActivityInfo}. */
public TargetPresentationGetter makePresentationGetter(ActivityInfo activityInfo) {
- return new ActivityInfoPresentationGetter(mContext, mIconDpi, activityInfo);
+ return new ActivityInfoPresentationGetter(
+ mIconFactoryProvider, mPackageManager, mIconDpi, activityInfo);
}
/** Make a {@link TargetPresentationGetter} for a {@link ResolveInfo}. */
public TargetPresentationGetter makePresentationGetter(ResolveInfo resolveInfo) {
- return new ResolveInfoPresentationGetter(mContext, mIconDpi, resolveInfo);
+ return new ResolveInfoPresentationGetter(
+ mIconFactoryProvider, mPackageManager, mIconDpi, resolveInfo);
}
}
@@ -76,7 +84,7 @@ public abstract class TargetPresentationGetter {
@Nullable
protected abstract String getAppLabelForSubstitutePermission();
- private final Context mContext;
+ private final Provider<SimpleIconFactory> mIconFactoryProvider;
private final int mIconDpi;
private final boolean mHasSubstitutePermission;
private final ApplicationInfo mAppInfo;
@@ -107,9 +115,10 @@ public abstract class TargetPresentationGetter {
drawable = mAppInfo.loadIcon(mPm);
}
- SimpleIconFactory iconFactory = SimpleIconFactory.obtain(mContext);
- Bitmap icon = iconFactory.createUserBadgedIconBitmap(drawable, userHandle);
- iconFactory.recycle();
+ Bitmap icon;
+ try (SimpleIconFactory iconFactory = mIconFactoryProvider.get()) {
+ icon = iconFactory.createUserBadgedIconBitmap(drawable, userHandle);
+ }
return icon;
}
@@ -159,9 +168,13 @@ public abstract class TargetPresentationGetter {
return res.getDrawableForDensity(resId, mIconDpi);
}
- private TargetPresentationGetter(Context context, int iconDpi, ApplicationInfo appInfo) {
- mContext = context;
- mPm = context.getPackageManager();
+ private TargetPresentationGetter(
+ Provider<SimpleIconFactory> iconfactoryProvider,
+ PackageManager packageManager,
+ int iconDpi,
+ ApplicationInfo appInfo) {
+ mIconFactoryProvider = iconfactoryProvider;
+ mPm = packageManager;
mAppInfo = appInfo;
mIconDpi = iconDpi;
mHasSubstitutePermission = (PackageManager.PERMISSION_GRANTED == mPm.checkPermission(
@@ -174,8 +187,11 @@ public abstract class TargetPresentationGetter {
private final ResolveInfo mResolveInfo;
ResolveInfoPresentationGetter(
- Context context, int iconDpi, ResolveInfo resolveInfo) {
- super(context, iconDpi, resolveInfo.activityInfo);
+ Provider<SimpleIconFactory> iconfactoryProvider,
+ PackageManager packageManager,
+ int iconDpi,
+ ResolveInfo resolveInfo) {
+ super(iconfactoryProvider, packageManager, iconDpi, resolveInfo.activityInfo);
mResolveInfo = resolveInfo;
}
@@ -221,8 +237,11 @@ public abstract class TargetPresentationGetter {
private final ActivityInfo mActivityInfo;
ActivityInfoPresentationGetter(
- Context context, int iconDpi, ActivityInfo activityInfo) {
- super(context, iconDpi, activityInfo.applicationInfo);
+ Provider<SimpleIconFactory> iconfactoryProvider,
+ PackageManager packageManager,
+ int iconDpi,
+ ActivityInfo activityInfo) {
+ super(iconfactoryProvider, packageManager, iconDpi, activityInfo.applicationInfo);
mActivityInfo = activityInfo;
}
diff --git a/java/src/com/android/intentresolver/icons/DefaultTargetDataLoader.kt b/java/src/com/android/intentresolver/icons/DefaultTargetDataLoader.kt
index e80a4a7c..1ff1ddfa 100644
--- a/java/src/com/android/intentresolver/icons/DefaultTargetDataLoader.kt
+++ b/java/src/com/android/intentresolver/icons/DefaultTargetDataLoader.kt
@@ -16,7 +16,6 @@
package com.android.intentresolver.icons
-import android.app.ActivityManager
import android.content.Context
import android.graphics.Bitmap
import android.graphics.drawable.BitmapDrawable
@@ -30,6 +29,7 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import com.android.intentresolver.Flags.targetHoverAndKeyboardFocusStates
import com.android.intentresolver.R
+import com.android.intentresolver.SimpleIconFactory
import com.android.intentresolver.TargetPresentationGetter
import com.android.intentresolver.chooser.DisplayResolveInfo
import com.android.intentresolver.chooser.SelectableTargetInfo
@@ -40,6 +40,7 @@ import dagger.assisted.AssistedInject
import dagger.hilt.android.qualifiers.ActivityContext
import java.util.concurrent.atomic.AtomicInteger
import java.util.function.Consumer
+import javax.inject.Provider
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asExecutor
@@ -50,14 +51,10 @@ class DefaultTargetDataLoader
constructor(
@ActivityContext private val context: Context,
@ActivityOwned private val lifecycle: Lifecycle,
+ private val iconFactoryProvider: Provider<SimpleIconFactory>,
+ private val presentationFactory: TargetPresentationGetter.Factory,
@Assisted private val isAudioCaptureDevice: Boolean,
) : TargetDataLoader {
- private val presentationFactory =
- TargetPresentationGetter.Factory(
- context,
- context.getSystemService(ActivityManager::class.java)?.launcherLargeIconDensity
- ?: error("Unable to access ActivityManager"),
- )
private val nextTaskId = AtomicInteger(0)
@GuardedBy("self") private val activeTasks = SparseArray<AsyncTask<*, *, *>>()
private val executor = Dispatchers.IO.asExecutor()
@@ -98,6 +95,7 @@ constructor(
context.createContextAsUser(userHandle, 0),
info,
presentationFactory,
+ iconFactoryProvider,
) { bitmap ->
removeTask(taskId)
callback.accept(bitmap?.toDrawable() ?: loadIconPlaceholder())
diff --git a/java/src/com/android/intentresolver/icons/LoadDirectShareIconTask.java b/java/src/com/android/intentresolver/icons/LoadDirectShareIconTask.java
index 641a0d6a..01f9330e 100644
--- a/java/src/com/android/intentresolver/icons/LoadDirectShareIconTask.java
+++ b/java/src/com/android/intentresolver/icons/LoadDirectShareIconTask.java
@@ -38,19 +38,24 @@ import com.android.intentresolver.util.UriFilters;
import java.util.function.Consumer;
+import javax.inject.Provider;
+
/**
* Loads direct share targets icons.
*/
class LoadDirectShareIconTask extends BaseLoadIconTask {
private static final String TAG = "DirectShareIconTask";
private final SelectableTargetInfo mTargetInfo;
+ private final Provider<SimpleIconFactory> mIconFactoryProvider;
LoadDirectShareIconTask(
Context context,
SelectableTargetInfo targetInfo,
TargetPresentationGetter.Factory presentationFactory,
+ Provider<SimpleIconFactory> iconFactoryProvider,
Consumer<Bitmap> callback) {
super(context, presentationFactory, callback);
+ mIconFactoryProvider = iconFactoryProvider;
mTargetInfo = targetInfo;
}
@@ -121,9 +126,10 @@ class LoadDirectShareIconTask extends BaseLoadIconTask {
Bitmap appIcon = mPresentationFactory.makePresentationGetter(info).getIconBitmap(null);
// Raster target drawable with appIcon as a badge
- SimpleIconFactory sif = SimpleIconFactory.obtain(context);
- Bitmap directShareBadgedIcon = sif.createAppBadgedIconBitmap(directShareIcon, appIcon);
- sif.recycle();
+ Bitmap directShareBadgedIcon;
+ try (SimpleIconFactory sif = mIconFactoryProvider.get()) {
+ directShareBadgedIcon = sif.createAppBadgedIconBitmap(directShareIcon, appIcon);
+ }
return directShareBadgedIcon;
}
diff --git a/java/src/com/android/intentresolver/icons/TargetDataLoaderModule.kt b/java/src/com/android/intentresolver/icons/TargetDataLoaderModule.kt
index 21ff654f..d6d4aae1 100644
--- a/java/src/com/android/intentresolver/icons/TargetDataLoaderModule.kt
+++ b/java/src/com/android/intentresolver/icons/TargetDataLoaderModule.kt
@@ -16,18 +16,39 @@
package com.android.intentresolver.icons
+import android.app.ActivityManager
import android.content.Context
+import android.content.pm.PackageManager
+import com.android.intentresolver.SimpleIconFactory
+import com.android.intentresolver.TargetPresentationGetter
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
import dagger.hilt.android.qualifiers.ActivityContext
import dagger.hilt.android.scopes.ActivityScoped
+import javax.inject.Provider
@Module
@InstallIn(ActivityComponent::class)
object TargetDataLoaderModule {
@Provides
+ fun simpleIconFactory(@ActivityContext context: Context): SimpleIconFactory =
+ SimpleIconFactory.obtain(context)
+
+ @Provides
+ fun presentationGetterFactory(
+ iconFactoryProvider: Provider<SimpleIconFactory>,
+ packageManager: PackageManager,
+ activityManager: ActivityManager,
+ ): TargetPresentationGetter.Factory =
+ TargetPresentationGetter.Factory(
+ iconFactoryProvider,
+ packageManager,
+ activityManager.launcherLargeIconDensity,
+ )
+
+ @Provides
@ActivityScoped
@Caching
fun cachingTargetDataLoader(
diff --git a/tests/unit/src/com/android/intentresolver/TargetPresentationGetterTest.kt b/tests/unit/src/com/android/intentresolver/TargetPresentationGetterTest.kt
index 92848b2c..b5b05eb9 100644
--- a/tests/unit/src/com/android/intentresolver/TargetPresentationGetterTest.kt
+++ b/tests/unit/src/com/android/intentresolver/TargetPresentationGetterTest.kt
@@ -32,32 +32,42 @@ class TargetPresentationGetterTest {
withSubstitutePermission: Boolean,
appLabel: String,
activityLabel: String,
- resolveInfoLabel: String
+ resolveInfoLabel: String,
): TargetPresentationGetter {
val testPackageInfo =
ResolverDataProvider.createPackageManagerMockedInfo(
withSubstitutePermission,
appLabel,
activityLabel,
- resolveInfoLabel
+ resolveInfoLabel,
+ )
+ val factory =
+ TargetPresentationGetter.Factory(
+ { SimpleIconFactory.obtain(testPackageInfo.ctx) },
+ testPackageInfo.ctx.packageManager,
+ 100,
)
- val factory = TargetPresentationGetter.Factory(testPackageInfo.ctx, 100)
return factory.makePresentationGetter(testPackageInfo.resolveInfo)
}
fun makeActivityInfoPresentationGetter(
withSubstitutePermission: Boolean,
appLabel: String?,
- activityLabel: String?
+ activityLabel: String?,
): TargetPresentationGetter {
val testPackageInfo =
ResolverDataProvider.createPackageManagerMockedInfo(
withSubstitutePermission,
appLabel,
activityLabel,
- ""
+ "",
+ )
+ val factory =
+ TargetPresentationGetter.Factory(
+ { SimpleIconFactory.obtain(testPackageInfo.ctx) },
+ testPackageInfo.ctx.packageManager,
+ 100,
)
- val factory = TargetPresentationGetter.Factory(testPackageInfo.ctx, 100)
return factory.makePresentationGetter(testPackageInfo.activityInfo)
}
@@ -158,7 +168,7 @@ class TargetPresentationGetterTest {
false,
"app_label",
"activity_label",
- "resolve_info_label"
+ "resolve_info_label",
)
assertThat(presentationGetter.getLabel()).isEqualTo("app_label")
assertThat(presentationGetter.getSubLabel()).isEqualTo("resolve_info_label")
@@ -192,7 +202,7 @@ class TargetPresentationGetterTest {
true,
"app_label",
"activity_label",
- "resolve_info_label"
+ "resolve_info_label",
)
assertThat(presentationGetter.getLabel()).isEqualTo("activity_label")
assertThat(presentationGetter.getSubLabel()).isEqualTo("resolve_info_label")