diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java index 1049314016..633091d87b 100644 --- a/src/com/android/launcher3/BaseActivity.java +++ b/src/com/android/launcher3/BaseActivity.java @@ -412,6 +412,8 @@ public abstract class BaseActivity extends Activity implements ActivityContext { public static T fromContext(Context context) { if (context instanceof BaseActivity) { return (T) context; + } else if (context instanceof ActivityContextDelegate) { + return (T) ((ActivityContextDelegate) context).mDelegate; } else if (context instanceof ContextWrapper) { return fromContext(((ContextWrapper) context).getBaseContext()); } else { diff --git a/src/com/android/launcher3/recyclerview/AllAppsRecyclerViewPool.kt b/src/com/android/launcher3/recyclerview/AllAppsRecyclerViewPool.kt index 43027da5fd..6d6b3b6497 100644 --- a/src/com/android/launcher3/recyclerview/AllAppsRecyclerViewPool.kt +++ b/src/com/android/launcher3/recyclerview/AllAppsRecyclerViewPool.kt @@ -26,7 +26,9 @@ import com.android.launcher3.config.FeatureFlags import com.android.launcher3.util.CancellableTask import com.android.launcher3.util.Executors.MAIN_EXECUTOR import com.android.launcher3.util.Executors.VIEW_PREINFLATION_EXECUTOR +import com.android.launcher3.util.Themes import com.android.launcher3.views.ActivityContext +import com.android.launcher3.views.ActivityContext.ActivityContextDelegate const val PREINFLATE_ICONS_ROW_COUNT = 4 const val EXTRA_ICONS_COUNT = 2 @@ -52,12 +54,28 @@ class AllAppsRecyclerViewPool : RecycledViewPool() { return } + // Create a separate context dedicated for all apps preinflation thread. The goal is to + // create a separate AssetManager obj internally to avoid lock contention with + // AssetManager obj that is associated with the launcher context on the main thread. + val allAppsPreInflationContext = + ActivityContextDelegate( + context.createConfigurationContext(context.resources.configuration), + Themes.getActivityThemeRes(context), + context + ) + // Because we perform onCreateViewHolder() on worker thread, we need a separate // adapter/inflator object as they are not thread-safe. Note that the adapter // just need to perform onCreateViewHolder(parent, VIEW_TYPE_ICON) so it doesn't need // data source information. val adapter: RecyclerView.Adapter = - object : BaseAllAppsAdapter(context, context.appsView.layoutInflater, null, null) { + object : + BaseAllAppsAdapter( + context, + context.appsView.layoutInflater.cloneInContext(allAppsPreInflationContext), + null, + null + ) { override fun setAppsPerRow(appsPerRow: Int) = Unit override fun getLayoutManager(): RecyclerView.LayoutManager? = null } diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java index bf43a229f3..cfac91a813 100644 --- a/src/com/android/launcher3/views/ActivityContext.java +++ b/src/com/android/launcher3/views/ActivityContext.java @@ -41,6 +41,7 @@ import android.os.IBinder; import android.os.Process; import android.os.UserHandle; import android.util.Log; +import android.view.ContextThemeWrapper; import android.view.Display; import android.view.LayoutInflater; import android.view.View; @@ -515,10 +516,21 @@ public interface ActivityContext { static T lookupContextNoThrow(Context context) { if (context instanceof ActivityContext) { return (T) context; + } else if (context instanceof ActivityContextDelegate acd) { + return (T) acd.mDelegate; } else if (context instanceof ContextWrapper) { return lookupContextNoThrow(((ContextWrapper) context).getBaseContext()); } else { return null; } } + + class ActivityContextDelegate extends ContextThemeWrapper { + public final ActivityContext mDelegate; + + public ActivityContextDelegate(Context base, int themeResId, ActivityContext delegate) { + super(base, themeResId); + mDelegate = delegate; + } + } }