Refactor all apps to depend on activity context.

The current AllAppsContainerView has been split into a base class and a
subclass for activities. The base class allows using all apps with an
activity context. A-Z and work profile tabs are supported, but search
and the hotseat still require an Activity.

Test: Manual. All apps should work the same.
Bug: 204696617
Change-Id: I3b146714bc11b3b3555d97623aab5d78ac836482
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index 80c2d9e..b47554f 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -49,7 +49,7 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
 import com.android.launcher3.allapps.search.DefaultSearchAdapterProvider;
 import com.android.launcher3.allapps.search.SearchAdapterProvider;
 import com.android.launcher3.logging.InstanceId;
@@ -340,7 +340,8 @@
      * Creates and returns {@link SearchAdapterProvider} for build variant specific search result
      * views
      */
-    public SearchAdapterProvider createSearchAdapterProvider(AllAppsContainerView allapps) {
-        return new DefaultSearchAdapterProvider(this, allapps);
+    public SearchAdapterProvider<?> createSearchAdapterProvider(
+            ActivityAllAppsContainerView<?> allApps) {
+        return new DefaultSearchAdapterProvider(this);
     }
 }
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 8e83c12..b90a875 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -122,7 +122,7 @@
 import com.android.launcher3.DropTarget.DragObject;
 import com.android.launcher3.accessibility.BaseAccessibilityDelegate.LauncherAction;
 import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
-import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
 import com.android.launcher3.allapps.AllAppsStore;
 import com.android.launcher3.allapps.AllAppsTransitionController;
 import com.android.launcher3.allapps.DiscoveryBounce;
@@ -315,7 +315,7 @@
 
     // Main container view for the all apps screen.
     @Thunk
-    AllAppsContainerView mAppsView;
+    ActivityAllAppsContainerView<Launcher> mAppsView;
     AllAppsTransitionController mAllAppsController;
 
     // Scrim view for the all apps and overview state.
@@ -1490,7 +1490,8 @@
         return mDragLayer;
     }
 
-    public AllAppsContainerView getAppsView() {
+    @Override
+    public ActivityAllAppsContainerView<Launcher> getAppsView() {
         return mAppsView;
     }
 
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
new file mode 100644
index 0000000..070b98e
--- /dev/null
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.allapps;
+
+import android.content.Context;
+import android.content.Intent;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+
+import androidx.core.graphics.ColorUtils;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.allapps.search.SearchAdapterProvider;
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.util.PackageManagerHelper;
+
+import java.util.Objects;
+
+/**
+ * All apps container view with search support for use in a dragging activity.
+ *
+ * @param <T> Type of context inflating all apps.
+ */
+public class ActivityAllAppsContainerView<T extends BaseDraggingActivity> extends
+        BaseAllAppsContainerView<T> {
+
+    protected SearchUiManager mSearchUiManager;
+    /**
+     * View that defines the search box. Result is rendered inside the recycler view defined in the
+     * base class.
+     */
+    private View mSearchContainer;
+    /** {@code true} when rendered view is in search state instead of the scroll state. */
+    private boolean mIsSearching;
+
+    public ActivityAllAppsContainerView(Context context) {
+        this(context, null);
+    }
+
+    public ActivityAllAppsContainerView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public ActivityAllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        mActivityContext.addOnDeviceProfileChangeListener(this);
+    }
+
+    public SearchUiManager getSearchUiManager() {
+        return mSearchUiManager;
+    }
+
+    public View getSearchView() {
+        return mSearchContainer;
+    }
+
+    /** Updates all apps container with the latest search query. */
+    public void setLastSearchQuery(String query) {
+        Intent marketSearchIntent = PackageManagerHelper.getMarketSearchIntent(
+                mActivityContext, query);
+        OnClickListener marketSearchClickListener = (v) -> mActivityContext.startActivitySafely(v,
+                marketSearchIntent, null);
+        for (int i = 0; i < mAH.size(); i++) {
+            mAH.get(i).adapter.setLastSearchQuery(query, marketSearchClickListener);
+        }
+        mIsSearching = true;
+        rebindAdapters();
+        mHeader.setCollapsed(true);
+    }
+
+    /** Invoke when the current search session is finished. */
+    public void onClearSearchResult() {
+        mIsSearching = false;
+        mHeader.setCollapsed(false);
+        rebindAdapters();
+        mHeader.reset(false);
+    }
+
+    /** Invoke when the search results change. */
+    public void onSearchResultsChanged() {
+        for (int i = 0; i < mAH.size(); i++) {
+            if (mAH.get(i).mRecyclerView != null) {
+                mAH.get(i).mRecyclerView.onSearchResultsChanged();
+            }
+        }
+    }
+
+    /** Handles selection on focused view and returns {@code true} on success. */
+    public boolean launchHighlightedItem() {
+        return getMainAdapterProvider().launchHighlightedItem();
+    }
+
+    @Override
+    protected SearchAdapterProvider<?> createMainAdapterProvider() {
+        return mActivityContext.createSearchAdapterProvider(this);
+    }
+
+    @Override
+    public boolean shouldContainerScroll(MotionEvent ev) {
+        // IF the MotionEvent is inside the search box, and the container keeps on receiving
+        // touch input, container should move down.
+        if (mActivityContext.getDragLayer().isEventOverView(mSearchContainer, ev)) {
+            return true;
+        }
+        return super.shouldContainerScroll(ev);
+    }
+
+    @Override
+    public void reset(boolean animate) {
+        super.reset(animate);
+        // Reset the search bar after transitioning home.
+        mSearchUiManager.resetSearch();
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mSearchContainer = findViewById(R.id.search_container_all_apps);
+        mSearchUiManager = (SearchUiManager) mSearchContainer;
+        mSearchUiManager.initializeSearch(this);
+    }
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        mSearchUiManager.preDispatchKeyEvent(event);
+        return super.dispatchKeyEvent(event);
+    }
+
+    @Override
+    public String getDescription() {
+        if (!mUsingTabs && mIsSearching) {
+            return getContext().getString(R.string.all_apps_search_results);
+        } else {
+            return super.getDescription();
+        }
+    }
+
+    @Override
+    protected boolean showTabs() {
+        return super.showTabs() && !mIsSearching;
+    }
+
+    @Override
+    protected void rebindAdapters(boolean force) {
+        super.rebindAdapters(force);
+        if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()
+                || getMainAdapterProvider().getDecorator() == null) {
+            return;
+        }
+
+        RecyclerView.ItemDecoration decoration = getMainAdapterProvider().getDecorator();
+        mAH.stream()
+                .map(adapterHolder -> adapterHolder.mRecyclerView)
+                .filter(Objects::nonNull)
+                .forEach(v -> {
+                    v.removeItemDecoration(decoration); // Remove in case it is already added.
+                    v.addItemDecoration(decoration);
+                });
+    }
+
+    @Override
+    protected void updateHeaderScroll(int scrolledOffset) {
+        super.updateHeaderScroll(scrolledOffset);
+        if (mSearchUiManager.getEditText() == null) {
+            return;
+        }
+
+        float prog = Utilities.boundToRange((float) scrolledOffset / mHeaderThreshold, 0f, 1f);
+        boolean bgVisible = mSearchUiManager.getBackgroundVisibility();
+        if (scrolledOffset == 0 && !mIsSearching) {
+            bgVisible = true;
+        } else if (scrolledOffset > mHeaderThreshold) {
+            bgVisible = false;
+        }
+        mSearchUiManager.setBackgroundVisibility(bgVisible, 1 - prog);
+    }
+
+    @Override
+    protected int getHeaderColor(float blendRatio) {
+        return ColorUtils.setAlphaComponent(
+                super.getHeaderColor(blendRatio),
+                (int) (mSearchContainer.getAlpha() * 255));
+    }
+
+    @Override
+    protected int getHeaderBottom() {
+        return super.getHeaderBottom() + mSearchContainer.getBottom();
+    }
+}
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index d5c9a53..f1ca9c0 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -18,7 +18,6 @@
 import static com.android.launcher3.touch.ItemLongClickListener.INSTANCE_ALL_APPS;
 
 import android.content.Context;
-import android.content.Intent;
 import android.content.res.Resources;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -38,21 +37,22 @@
 import androidx.recyclerview.widget.GridLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.R;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
-import com.android.launcher3.util.PackageManagerHelper;
+import com.android.launcher3.views.ActivityContext;
 
 import java.util.Arrays;
 import java.util.List;
 
 /**
  * The grid view adapter of all the apps.
+ *
+ * @param <T> Type of context inflating all apps.
  */
-public class AllAppsGridAdapter extends
+public class AllAppsGridAdapter<T extends Context & ActivityContext> extends
         RecyclerView.Adapter<AllAppsGridAdapter.ViewHolder> {
 
     public static final String TAG = "AppsGridAdapter";
@@ -256,9 +256,9 @@
         }
     }
 
-    private final BaseDraggingActivity mLauncher;
+    private final T mActivityContext;
     private final LayoutInflater mLayoutInflater;
-    private final AlphabeticalAppsList mApps;
+    private final AlphabeticalAppsList<T> mApps;
     private final GridLayoutManager mGridLayoutMgr;
     private final GridSpanSizer mGridSizer;
 
@@ -271,27 +271,28 @@
 
     // The text to show when there are no search results and no market search handler.
     protected String mEmptySearchMessage;
-    // The intent to send off to the market app, updated each time the search query changes.
-    private Intent mMarketSearchIntent;
+    // The click listener to send off to the market app, updated each time the search query changes.
+    private OnClickListener mMarketSearchClickListener;
 
     private final int mExtraHeight;
 
-    public AllAppsGridAdapter(BaseDraggingActivity launcher, LayoutInflater inflater,
-            AlphabeticalAppsList apps, BaseAdapterProvider[] adapterProviders) {
-        Resources res = launcher.getResources();
-        mLauncher = launcher;
+    public AllAppsGridAdapter(T activityContext, LayoutInflater inflater,
+            AlphabeticalAppsList<T> apps, BaseAdapterProvider[] adapterProviders) {
+        Resources res = activityContext.getResources();
+        mActivityContext = activityContext;
         mApps = apps;
         mEmptySearchMessage = res.getString(R.string.all_apps_loading_message);
         mGridSizer = new GridSpanSizer();
-        mGridLayoutMgr = new AppsGridLayoutManager(launcher);
+        mGridLayoutMgr = new AppsGridLayoutManager(mActivityContext);
         mGridLayoutMgr.setSpanSizeLookup(mGridSizer);
         mLayoutInflater = inflater;
 
-        mOnIconClickListener = launcher.getItemOnClickListener();
+        mOnIconClickListener = mActivityContext.getItemOnClickListener();
 
         mAdapterProviders = adapterProviders;
-        setAppsPerRow(mLauncher.getDeviceProfile().numShownAllAppsColumns);
-        mExtraHeight = launcher.getResources().getDimensionPixelSize(R.dimen.all_apps_height_extra);
+        setAppsPerRow(mActivityContext.getDeviceProfile().numShownAllAppsColumns);
+        mExtraHeight = mActivityContext.getResources().getDimensionPixelSize(
+                R.dimen.all_apps_height_extra);
     }
 
     public void setAppsPerRow(int appsPerRow) {
@@ -334,10 +335,10 @@
      * Sets the last search query that was made, used to show when there are no results and to also
      * seed the intent for searching the market.
      */
-    public void setLastSearchQuery(String query) {
-        Resources res = mLauncher.getResources();
+    public void setLastSearchQuery(String query, OnClickListener marketSearchClickListener) {
+        Resources res = mActivityContext.getResources();
         mEmptySearchMessage = res.getString(R.string.all_apps_no_search_results, query);
-        mMarketSearchIntent = PackageManagerHelper.getMarketSearchIntent(mLauncher, query);
+        mMarketSearchClickListener = marketSearchClickListener;
     }
 
     /**
@@ -360,7 +361,8 @@
                 icon.setOnClickListener(mOnIconClickListener);
                 icon.setOnLongClickListener(mOnIconLongClickListener);
                 // Ensure the all apps icon height matches the workspace icons in portrait mode.
-                icon.getLayoutParams().height = mLauncher.getDeviceProfile().allAppsCellHeightPx;
+                icon.getLayoutParams().height =
+                        mActivityContext.getDeviceProfile().allAppsCellHeightPx;
                 if (FeatureFlags.ENABLE_TWOLINE_ALLAPPS.get()) {
                     icon.getLayoutParams().height += mExtraHeight;
                 }
@@ -371,8 +373,7 @@
             case VIEW_TYPE_SEARCH_MARKET:
                 View searchMarketView = mLayoutInflater.inflate(R.layout.all_apps_search_market,
                         parent, false);
-                searchMarketView.setOnClickListener(v -> mLauncher.startActivitySafely(
-                        v, mMarketSearchIntent, null));
+                searchMarketView.setOnClickListener(mMarketSearchClickListener);
                 return new ViewHolder(searchMarketView);
             case VIEW_TYPE_ALL_APPS_DIVIDER:
                 return new ViewHolder(mLayoutInflater.inflate(
@@ -407,7 +408,7 @@
                 break;
             case VIEW_TYPE_SEARCH_MARKET:
                 TextView searchView = (TextView) holder.itemView;
-                if (mMarketSearchIntent != null) {
+                if (mMarketSearchClickListener != null) {
                     searchView.setVisibility(View.VISIBLE);
                 } else {
                     searchView.setVisibility(View.GONE);
diff --git a/src/com/android/launcher3/allapps/AllAppsPagedView.java b/src/com/android/launcher3/allapps/AllAppsPagedView.java
index 3cc9ce6..872503a 100644
--- a/src/com/android/launcher3/allapps/AllAppsPagedView.java
+++ b/src/com/android/launcher3/allapps/AllAppsPagedView.java
@@ -21,13 +21,13 @@
 import android.content.Context;
 import android.util.AttributeSet;
 
-import com.android.launcher3.Launcher;
 import com.android.launcher3.PagedView;
+import com.android.launcher3.views.ActivityContext;
 import com.android.launcher3.workprofile.PersonalWorkPagedView;
 
 /**
- *  A {@link PagedView} for showing different views for the personal and work profile respectively
- *  in the {@link AllAppsContainerView}.
+ * A {@link PagedView} for showing different views for the personal and work profile respectively
+ * in the {@link BaseAllAppsContainerView}.
  */
 public class AllAppsPagedView extends PersonalWorkPagedView {
 
@@ -47,7 +47,7 @@
     protected boolean snapToPageWithVelocity(int whichPage, int velocity) {
         boolean resp = super.snapToPageWithVelocity(whichPage, velocity);
         if (resp && whichPage != mCurrentPage) {
-            Launcher.getLauncher(getContext()).getStatsLogManager().logger()
+            ActivityContext.lookupContext(getContext()).getStatsLogManager().logger()
                     .log(mCurrentPage < whichPage
                             ? LAUNCHER_ALLAPPS_SWIPE_TO_WORK_TAB
                             : LAUNCHER_ALLAPPS_SWIPE_TO_PERSONAL_TAB);
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index bccd9b4..c2cb845 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -36,7 +36,6 @@
 
 import androidx.recyclerview.widget.RecyclerView;
 
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.BaseRecyclerView;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.LauncherAppState;
@@ -58,7 +57,7 @@
     private static final boolean DEBUG = false;
     private static final boolean DEBUG_LATENCY = Utilities.isPropertyEnabled(SEARCH_LOGGING);
 
-    private AlphabeticalAppsList mApps;
+    private AlphabeticalAppsList<?> mApps;
     private final int mNumAppsPerRow;
 
     // The specific view heights that we use to calculate scroll
@@ -104,16 +103,16 @@
     /**
      * Sets the list of apps in this view, used to determine the fastscroll position.
      */
-    public void setApps(AlphabeticalAppsList apps) {
+    public void setApps(AlphabeticalAppsList<?> apps) {
         mApps = apps;
     }
 
-    public AlphabeticalAppsList getApps() {
+    public AlphabeticalAppsList<?> getApps() {
         return mApps;
     }
 
     private void updatePoolSize() {
-        DeviceProfile grid = BaseDraggingActivity.fromContext(getContext()).getDeviceProfile();
+        DeviceProfile grid = ActivityContext.lookupContext(getContext()).getDeviceProfile();
         RecyclerView.RecycledViewPool pool = getRecycledViewPool();
         int approxRows = (int) Math.ceil(grid.availableHeightPx / grid.allAppsIconSizePx);
         pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_EMPTY_SEARCH, 1);
@@ -201,7 +200,7 @@
     public void onScrollStateChanged(int state) {
         super.onScrollStateChanged(state);
 
-        StatsLogManager mgr = BaseDraggingActivity.fromContext(getContext()).getStatsLogManager();
+        StatsLogManager mgr = ActivityContext.lookupContext(getContext()).getStatsLogManager();
         switch (state) {
             case SCROLL_STATE_DRAGGING:
                 requestFocus();
@@ -470,7 +469,7 @@
      * Returns distance between left and right app icons
      */
     public int getTabWidth() {
-        DeviceProfile grid = BaseDraggingActivity.fromContext(getContext()).getDeviceProfile();
+        DeviceProfile grid = ActivityContext.lookupContext(getContext()).getDeviceProfile();
         int totalWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
         int iconPadding = totalWidth / grid.numShownAllAppsColumns - grid.allAppsIconSizePx;
         return totalWidth - iconPadding - grid.allAppsIconDrawablePaddingPx;
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index fc78bea..b6a2459 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -75,7 +75,7 @@
                 }
             };
 
-    private AllAppsContainerView mAppsView;
+    private ActivityAllAppsContainerView<Launcher> mAppsView;
 
     private final Launcher mLauncher;
     private boolean mIsVerticalLayout;
@@ -201,7 +201,7 @@
     /**
      * see Launcher#setupViews
      */
-    public void setupViews(ScrimView scrimView, AllAppsContainerView appsView) {
+    public void setupViews(ScrimView scrimView, ActivityAllAppsContainerView<Launcher> appsView) {
         mScrimView = scrimView;
         mAppsView = appsView;
         if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && Utilities.ATLEAST_R) {
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index ce5c589..1a1d521 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -18,12 +18,12 @@
 
 import android.content.Context;
 
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.util.ItemInfoMatcher;
 import com.android.launcher3.util.LabelComparator;
+import com.android.launcher3.views.ActivityContext;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -35,8 +35,11 @@
 
 /**
  * The alphabetically sorted list of applications.
+ *
+ * @param <T> Type of context inflating this view.
  */
-public class AlphabeticalAppsList implements AllAppsStore.OnUpdateListener {
+public class AlphabeticalAppsList<T extends Context & ActivityContext> implements
+        AllAppsStore.OnUpdateListener {
 
     public static final String TAG = "AlphabeticalAppsList";
 
@@ -64,7 +67,7 @@
     }
 
 
-    private final BaseDraggingActivity mLauncher;
+    private final T mActivityContext;
 
     // The set of apps from the system
     private final List<AppInfo> mApps = new ArrayList<>();
@@ -79,7 +82,7 @@
 
     // The of ordered component names as a result of a search query
     private ArrayList<AdapterItem> mSearchResults;
-    private AllAppsGridAdapter mAdapter;
+    private AllAppsGridAdapter<T> mAdapter;
     private AppInfoComparator mAppNameComparator;
     private final int mNumAppsPerRow;
     private int mNumAppRowsInAdapter;
@@ -88,10 +91,10 @@
     public AlphabeticalAppsList(Context context, AllAppsStore appsStore,
             WorkAdapterProvider adapterProvider) {
         mAllAppsStore = appsStore;
-        mLauncher = BaseDraggingActivity.fromContext(context);
+        mActivityContext = ActivityContext.lookupContext(context);
         mAppNameComparator = new AppInfoComparator(context);
         mWorkAdapterProvider = adapterProvider;
-        mNumAppsPerRow = mLauncher.getDeviceProfile().inv.numColumns;
+        mNumAppsPerRow = mActivityContext.getDeviceProfile().inv.numColumns;
         mAllAppsStore.addUpdateListener(this);
     }
 
@@ -103,7 +106,7 @@
     /**
      * Sets the adapter to notify when this dataset changes.
      */
-    public void setAdapter(AllAppsGridAdapter adapter) {
+    public void setAdapter(AllAppsGridAdapter<T> adapter) {
         mAdapter = adapter;
     }
 
@@ -229,7 +232,7 @@
 
         // As a special case for some languages (currently only Simplified Chinese), we may need to
         // coalesce sections
-        Locale curLocale = mLauncher.getResources().getConfiguration().locale;
+        Locale curLocale = mActivityContext.getResources().getConfiguration().locale;
         boolean localeRequiresSectionSorting = curLocale.equals(Locale.SIMPLIFIED_CHINESE);
         if (localeRequiresSectionSorting) {
             // Compute the section headers. We use a TreeMap with the section name comparator to
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
similarity index 67%
rename from src/com/android/launcher3/allapps/AllAppsContainerView.java
rename to src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
index f06ec4f..c1f0e06 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
@@ -31,15 +31,12 @@
 import android.os.Parcelable;
 import android.os.Process;
 import android.os.UserManager;
-import android.text.SpannableStringBuilder;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.SparseArray;
-import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.WindowInsets;
 
 import androidx.annotation.NonNull;
@@ -50,7 +47,6 @@
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
 import com.android.launcher3.DragSource;
@@ -60,22 +56,27 @@
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.allapps.search.SearchAdapterProvider;
-import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.keyboard.FocusedItemDecorator;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.util.ItemInfoMatcher;
 import com.android.launcher3.util.Themes;
+import com.android.launcher3.views.ActivityContext;
 import com.android.launcher3.views.RecyclerViewFastScroller;
 import com.android.launcher3.views.ScrimView;
 import com.android.launcher3.views.SpringRelativeLayout;
 import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.OnActivePageChangedListener;
 
+import java.util.Arrays;
+import java.util.List;
+
 /**
- * The all apps view container.
+ * Base all apps view container.
+ *
+ * @param <T> Type of context inflating all apps.
  */
-public class AllAppsContainerView extends SpringRelativeLayout implements DragSource,
-        Insettable, OnDeviceProfileChangeListener, OnActivePageChangedListener,
-        ScrimView.ScrimDrawingController {
+public abstract class BaseAllAppsContainerView<T extends Context & ActivityContext> extends
+        SpringRelativeLayout implements DragSource, Insettable, OnDeviceProfileChangeListener,
+        OnActivePageChangedListener, ScrimView.ScrimDrawingController {
 
     private static final String BUNDLE_KEY_CURRENT_PAGE = "launcher.allapps.current_page";
 
@@ -85,10 +86,12 @@
     private final Paint mHeaderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
     private final Rect mInsets = new Rect();
 
-    protected final BaseDraggingActivity mLauncher;
-    protected final AdapterHolder[] mAH;
+    /** Context of an activity or window that is inflating this container. */
+    protected final T mActivityContext;
+    protected final List<AdapterHolder> mAH;
     protected final ItemInfoMatcher mPersonalMatcher = ItemInfoMatcher.ofUser(
             Process.myUserHandle());
+    private final SearchAdapterProvider<?> mMainAdapterProvider;
     private final AllAppsStore mAllAppsStore = new AllAppsStore();
 
     private final RecyclerView.OnScrollListener mScrollListener =
@@ -100,69 +103,58 @@
             };
     private final WorkProfileManager mWorkManager;
 
-
     private final Paint mNavBarScrimPaint;
     private int mNavBarScrimHeight = 0;
 
-    protected SearchUiManager mSearchUiManager;
-    private View mSearchContainer;
     private AllAppsPagedView mViewPager;
 
     protected FloatingHeaderView mHeader;
 
-
-    private SpannableStringBuilder mSearchQueryBuilder = null;
-
     protected boolean mUsingTabs;
-    private boolean mIsSearching;
     private boolean mHasWorkApps;
 
     protected RecyclerViewFastScroller mTouchHandler;
     protected final Point mFastScrollerOffset = new Point();
 
-    private SearchAdapterProvider mSearchAdapterProvider;
     private final int mScrimColor;
     private final int mHeaderProtectionColor;
-    private final float mHeaderThreshold;
+    protected final float mHeaderThreshold;
     private ScrimView mScrimView;
     private int mHeaderColor;
     private int mTabsProtectionAlpha;
 
-    public AllAppsContainerView(Context context) {
-        this(context, null);
-    }
-
-    public AllAppsContainerView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public AllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
+    protected BaseAllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-
-        mLauncher = BaseDraggingActivity.fromContext(context);
+        mActivityContext = ActivityContext.lookupContext(context);
+        mMainAdapterProvider = createMainAdapterProvider();
 
         mScrimColor = Themes.getAttrColor(context, R.attr.allAppsScrimColor);
         mHeaderThreshold = getResources().getDimensionPixelSize(
                 R.dimen.dynamic_grid_cell_border_spacing);
         mHeaderProtectionColor = Themes.getAttrColor(context, R.attr.allappsHeaderProtectionColor);
 
-        mLauncher.addOnDeviceProfileChangeListener(this);
-
-        mSearchAdapterProvider = mLauncher.createSearchAdapterProvider(this);
-
-        mAH = new AdapterHolder[2];
-
-        mWorkManager = new WorkProfileManager(mLauncher.getSystemService(UserManager.class), this,
-                Utilities.getPrefs(mLauncher));
-        mAH[AdapterHolder.MAIN] = new AdapterHolder(false /* isWork */);
-        mAH[AdapterHolder.WORK] = new AdapterHolder(true /* isWork */);
+        mWorkManager = new WorkProfileManager(
+                mActivityContext.getSystemService(UserManager.class),
+                this,
+                Utilities.getPrefs(mActivityContext));
+        mAH = Arrays.asList(null, null);
+        mAH.set(AdapterHolder.MAIN, new AdapterHolder(false /* isWork */));
+        mAH.set(AdapterHolder.WORK, new AdapterHolder(true /* isWork */));
 
         mNavBarScrimPaint = new Paint();
         mNavBarScrimPaint.setColor(Themes.getAttrColor(context, R.attr.allAppsNavBarScrimColor));
 
         mAllAppsStore.addUpdateListener(this::onAppsUpdated);
 
-        updateBackground(mLauncher.getDeviceProfile());
+        updateBackground(mActivityContext.getDeviceProfile());
+    }
+
+    /** Creates the adapter provider for the main section. */
+    protected abstract SearchAdapterProvider<?> createMainAdapterProvider();
+
+    /** The adapter provider for the main section. */
+    public final SearchAdapterProvider<?> getMainAdapterProvider() {
+        return mMainAdapterProvider;
     }
 
     @Override
@@ -219,11 +211,11 @@
     public void onDeviceProfileChanged(DeviceProfile dp) {
         for (AdapterHolder holder : mAH) {
             holder.adapter.setAppsPerRow(dp.numShownAllAppsColumns);
-            if (holder.recyclerView != null) {
+            if (holder.mRecyclerView != null) {
                 // Remove all views and clear the pool, while keeping the data same. After this
                 // call, all the viewHolders will be recreated.
-                holder.recyclerView.swapAdapter(holder.recyclerView.getAdapter(), true);
-                holder.recyclerView.getRecycledViewPool().clear();
+                holder.mRecyclerView.swapAdapter(holder.mRecyclerView.getAdapter(), true);
+                holder.mRecyclerView.getRecycledViewPool().clear();
             }
         }
         updateBackground(dp);
@@ -244,7 +236,7 @@
             }
         }
         mHasWorkApps = hasWorkApps;
-        if (!mAH[AdapterHolder.MAIN].appsList.hasFilter()) {
+        if (!mAH.get(AdapterHolder.MAIN).mAppsList.hasFilter()) {
             rebindAdapters();
             if (hasWorkApps) {
                 mWorkManager.reset();
@@ -256,28 +248,24 @@
      * Returns whether the view itself will handle the touch event or not.
      */
     public boolean shouldContainerScroll(MotionEvent ev) {
-        // IF the MotionEvent is inside the search box, and the container keeps on receiving
-        // touch input, container should move down.
-        if (mLauncher.getDragLayer().isEventOverView(mSearchContainer, ev)) {
-            return true;
-        }
+        // TODO(b/216203409) Support dragging down from bottom sheet divider, if present.
         AllAppsRecyclerView rv = getActiveRecyclerView();
         if (rv == null) {
             return true;
         }
-        if (rv.getScrollbar().getThumbOffsetY() >= 0 &&
-                mLauncher.getDragLayer().isEventOverView(rv.getScrollbar(), ev)) {
+        if (rv.getScrollbar().getThumbOffsetY() >= 0
+                && mActivityContext.getDragLayer().isEventOverView(rv.getScrollbar(), ev)) {
             return false;
         }
-        return rv.shouldContainerScroll(ev, mLauncher.getDragLayer());
+        return rv.shouldContainerScroll(ev, mActivityContext.getDragLayer());
     }
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         if (ev.getAction() == MotionEvent.ACTION_DOWN) {
             AllAppsRecyclerView rv = getActiveRecyclerView();
-            if (rv != null &&
-                    rv.getScrollbar().isHitInParent(ev.getX(), ev.getY(), mFastScrollerOffset)) {
+            if (rv != null && rv.getScrollbar().isHitInParent(ev.getX(), ev.getY(),
+                    mFastScrollerOffset)) {
                 mTouchHandler = rv.getScrollbar();
             } else {
                 mTouchHandler = null;
@@ -308,6 +296,7 @@
         return false;
     }
 
+    /** Description of the container view based on its current state. */
     public String getDescription() {
         @StringRes int descriptionRes;
         if (mUsingTabs) {
@@ -315,19 +304,18 @@
                     mViewPager.getNextPage() == 0
                             ? R.string.all_apps_button_personal_label
                             : R.string.all_apps_button_work_label;
-        } else if (mIsSearching) {
-            descriptionRes = R.string.all_apps_search_results;
         } else {
             descriptionRes = R.string.all_apps_button_label;
         }
         return getContext().getString(descriptionRes);
     }
 
+    /** The current recycler view visible in the container. */
     public AllAppsRecyclerView getActiveRecyclerView() {
         if (!mUsingTabs || mViewPager.getNextPage() == 0) {
-            return mAH[AdapterHolder.MAIN].recyclerView;
+            return mAH.get(AdapterHolder.MAIN).mRecyclerView;
         } else {
-            return mAH[AdapterHolder.WORK].recyclerView;
+            return mAH.get(AdapterHolder.WORK).mRecyclerView;
         }
     }
 
@@ -339,16 +327,15 @@
      * Resets the state of AllApps.
      */
     public void reset(boolean animate) {
-        for (int i = 0; i < mAH.length; i++) {
-            if (mAH[i].recyclerView != null) {
-                mAH[i].recyclerView.scrollToTop();
+        for (int i = 0; i < mAH.size(); i++) {
+            if (mAH.get(i).mRecyclerView != null) {
+                mAH.get(i).mRecyclerView.scrollToTop();
             }
         }
         if (isHeaderVisible()) {
             mHeader.reset(animate);
         }
-        // Reset the search bar and base recycler view after transitioning home
-        mSearchUiManager.resetSearch();
+        // Reset the base recycler view after transitioning home.
         updateHeaderScroll(0);
     }
 
@@ -366,20 +353,6 @@
 
         mHeader = findViewById(R.id.all_apps_header);
         rebindAdapters(true /* force */);
-
-        mSearchContainer = findViewById(R.id.search_container_all_apps);
-        mSearchUiManager = (SearchUiManager) mSearchContainer;
-        mSearchUiManager.initializeSearch(this);
-    }
-
-    public SearchUiManager getSearchUiManager() {
-        return mSearchUiManager;
-    }
-
-    @Override
-    public boolean dispatchKeyEvent(KeyEvent event) {
-        mSearchUiManager.preDispatchKeyEvent(event);
-        return super.dispatchKeyEvent(event);
     }
 
     @Override
@@ -389,15 +362,15 @@
     @Override
     public void setInsets(Rect insets) {
         mInsets.set(insets);
-        DeviceProfile grid = mLauncher.getDeviceProfile();
+        DeviceProfile grid = mActivityContext.getDeviceProfile();
 
-        for (int i = 0; i < mAH.length; i++) {
-            mAH[i].padding.bottom = insets.bottom;
-            mAH[i].padding.left = mAH[i].padding.right = grid.allAppsLeftRightPadding;
-            mAH[i].applyPadding();
+        for (int i = 0; i < mAH.size(); i++) {
+            mAH.get(i).mPadding.bottom = insets.bottom;
+            mAH.get(i).mPadding.left = mAH.get(i).mPadding.right = grid.allAppsLeftRightPadding;
+            mAH.get(i).applyPadding();
         }
 
-        ViewGroup.MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();
+        MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();
         mlp.topMargin = grid.isTablet ? insets.top : 0;
         int leftRightMargin = grid.allAppsLeftRightMargin;
         mlp.leftMargin = insets.left + leftRightMargin;
@@ -433,57 +406,60 @@
         }
     }
 
-    private void rebindAdapters() {
+    protected void rebindAdapters() {
         rebindAdapters(false /* force */);
     }
 
     protected void rebindAdapters(boolean force) {
-        boolean showTabs = mHasWorkApps && !mIsSearching;
+        boolean showTabs = showTabs();
         if (showTabs == mUsingTabs && !force) {
             return;
         }
         replaceRVContainer(showTabs);
         mUsingTabs = showTabs;
 
-        mAllAppsStore.unregisterIconContainer(mAH[AdapterHolder.MAIN].recyclerView);
-        mAllAppsStore.unregisterIconContainer(mAH[AdapterHolder.WORK].recyclerView);
+        mAllAppsStore.unregisterIconContainer(mAH.get(AdapterHolder.MAIN).mRecyclerView);
+        mAllAppsStore.unregisterIconContainer(mAH.get(AdapterHolder.WORK).mRecyclerView);
 
         if (mUsingTabs) {
-            mAH[AdapterHolder.MAIN].setup(mViewPager.getChildAt(0), mPersonalMatcher);
-            mAH[AdapterHolder.WORK].setup(mViewPager.getChildAt(1), mWorkManager.getMatcher());
-            mAH[AdapterHolder.WORK].recyclerView.setId(R.id.apps_list_view_work);
+            mAH.get(AdapterHolder.MAIN).setup(mViewPager.getChildAt(0), mPersonalMatcher);
+            mAH.get(AdapterHolder.WORK).setup(mViewPager.getChildAt(1), mWorkManager.getMatcher());
+            mAH.get(AdapterHolder.WORK).mRecyclerView.setId(R.id.apps_list_view_work);
             mViewPager.getPageIndicator().setActiveMarker(AdapterHolder.MAIN);
             findViewById(R.id.tab_personal)
                     .setOnClickListener((View view) -> {
                         if (mViewPager.snapToPage(AdapterHolder.MAIN)) {
-                            mLauncher.getStatsLogManager().logger()
+                            mActivityContext.getStatsLogManager().logger()
                                     .log(LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB);
                         }
                     });
             findViewById(R.id.tab_work)
                     .setOnClickListener((View view) -> {
                         if (mViewPager.snapToPage(AdapterHolder.WORK)) {
-                            mLauncher.getStatsLogManager().logger()
+                            mActivityContext.getStatsLogManager().logger()
                                     .log(LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB);
                         }
                     });
             onActivePageChanged(mViewPager.getNextPage());
         } else {
-            mAH[AdapterHolder.MAIN].setup(findViewById(R.id.apps_list_view), null);
-            mAH[AdapterHolder.WORK].recyclerView = null;
+            mAH.get(AdapterHolder.MAIN).setup(findViewById(R.id.apps_list_view), null);
+            mAH.get(AdapterHolder.WORK).mRecyclerView = null;
         }
         setupHeader();
 
-        mAllAppsStore.registerIconContainer(mAH[AdapterHolder.MAIN].recyclerView);
-        mAllAppsStore.registerIconContainer(mAH[AdapterHolder.WORK].recyclerView);
+        mAllAppsStore.registerIconContainer(mAH.get(AdapterHolder.MAIN).mRecyclerView);
+        mAllAppsStore.registerIconContainer(mAH.get(AdapterHolder.WORK).mRecyclerView);
     }
 
+    protected boolean showTabs() {
+        return mHasWorkApps;
+    }
 
     private void replaceRVContainer(boolean showTabs) {
         for (AdapterHolder adapterHolder : mAH) {
-            if (adapterHolder.recyclerView != null) {
-                adapterHolder.recyclerView.setLayoutManager(null);
-                adapterHolder.recyclerView.setAdapter(null);
+            if (adapterHolder.mRecyclerView != null) {
+                adapterHolder.mRecyclerView.setLayoutManager(null);
+                adapterHolder.mRecyclerView.setAdapter(null);
             }
         }
         View oldView = getRecyclerViewContainer();
@@ -497,7 +473,8 @@
             mViewPager.initParentViews(this);
             mViewPager.getPageIndicator().setOnActivePageChangedListener(this);
             if (mWorkManager.attachWorkModeSwitch()) {
-                mWorkManager.getWorkModeSwitch().post(() -> mAH[AdapterHolder.WORK].applyPadding());
+                mWorkManager.getWorkModeSwitch().post(
+                        () -> mAH.get(AdapterHolder.WORK).applyPadding());
             }
         } else {
             mWorkManager.detachWorkModeSwitch();
@@ -512,8 +489,8 @@
     @Override
     public void onActivePageChanged(int currentActivePage) {
         mHeader.setMainActive(currentActivePage == AdapterHolder.MAIN);
-        if (mAH[currentActivePage].recyclerView != null) {
-            mAH[currentActivePage].recyclerView.bindFastScrollbar();
+        if (mAH.get(currentActivePage).mRecyclerView != null) {
+            mAH.get(currentActivePage).mRecyclerView.bindFastScrollbar();
         }
         reset(true /* animate */);
 
@@ -535,95 +512,53 @@
         return isDescendantViewVisible(R.id.tab_personal);
     }
 
-    // Used by tests only
+    @VisibleForTesting
     public boolean isWorkTabVisible() {
         return isDescendantViewVisible(R.id.tab_work);
     }
 
-    public AlphabeticalAppsList getApps() {
-        return mAH[AdapterHolder.MAIN].appsList;
+    public AlphabeticalAppsList<T> getApps() {
+        return mAH.get(AdapterHolder.MAIN).mAppsList;
     }
 
     public FloatingHeaderView getFloatingHeaderView() {
         return mHeader;
     }
 
-    public View getSearchView() {
-        return mSearchContainer;
-    }
-
+    @VisibleForTesting
     public View getContentView() {
         return mViewPager == null ? getActiveRecyclerView() : mViewPager;
     }
 
+    /** The current page visible in all apps. */
     public int getCurrentPage() {
         return mViewPager != null ? mViewPager.getCurrentPage() : AdapterHolder.MAIN;
     }
 
-    /**
-     * Handles selection on focused view and returns success
-     */
-    public boolean launchHighlightedItem() {
-        if (mSearchAdapterProvider == null) return false;
-        return mSearchAdapterProvider.launchHighlightedItem();
-    }
-
-    public SearchAdapterProvider getSearchAdapterProvider() {
-        return mSearchAdapterProvider;
-    }
-
+    /** The scroll bar for the active recycler view. */
     public RecyclerViewFastScroller getScrollBar() {
         AllAppsRecyclerView rv = getActiveRecyclerView();
         return rv == null ? null : rv.getScrollbar();
     }
 
-    public void setupHeader() {
+    void setupHeader() {
         mHeader.setVisibility(View.VISIBLE);
-        mHeader.setup(mAH, mAH[AllAppsContainerView.AdapterHolder.WORK].recyclerView == null);
+        mHeader.setup(mAH, mAH.get(AdapterHolder.WORK).mRecyclerView == null);
 
         int padding = mHeader.getMaxTranslation();
-        for (int i = 0; i < mAH.length; i++) {
-            mAH[i].padding.top = padding;
-            mAH[i].applyPadding();
-            if (mAH[i].recyclerView != null) {
-                mAH[i].recyclerView.scrollToTop();
+        for (int i = 0; i < mAH.size(); i++) {
+            mAH.get(i).mPadding.top = padding;
+            mAH.get(i).applyPadding();
+            if (mAH.get(i).mRecyclerView != null) {
+                mAH.get(i).mRecyclerView.scrollToTop();
             }
         }
     }
 
-    public void setLastSearchQuery(String query) {
-        for (int i = 0; i < mAH.length; i++) {
-            mAH[i].adapter.setLastSearchQuery(query);
-        }
-        mIsSearching = true;
-        rebindAdapters();
-        mHeader.setCollapsed(true);
-    }
-
-    public void onClearSearchResult() {
-        mIsSearching = false;
-        mHeader.setCollapsed(false);
-        rebindAdapters();
-        mHeader.reset(false);
-    }
-
-    public void onSearchResultsChanged() {
-        for (int i = 0; i < mAH.length; i++) {
-            if (mAH[i].recyclerView != null) {
-                mAH[i].recyclerView.onSearchResultsChanged();
-            }
-        }
-    }
-
+    /** @see View#setVerticalFadingEdgeEnabled(boolean). */
     public void setRecyclerViewVerticalFadingEdgeEnabled(boolean enabled) {
-        for (int i = 0; i < mAH.length; i++) {
-            mAH[i].applyVerticalFadingEdgeEnabled(enabled);
-        }
-    }
-
-    public void addElevationController(RecyclerView.OnScrollListener scrollListener) {
-        if (!mUsingTabs) {
-            mAH[AdapterHolder.MAIN].recyclerView.addOnScrollListener(scrollListener);
+        for (int i = 0; i < mAH.size(); i++) {
+            mAH.get(i).applyVerticalFadingEdgeEnabled(enabled);
         }
     }
 
@@ -632,7 +567,7 @@
     }
 
     /**
-     * Adds an update listener to {@param animator} that adds springs to the animation.
+     * Adds an update listener to animator that adds springs to the animation.
      */
     public void addSpringFromFlingUpdateListener(ValueAnimator animator,
             float velocity /* release velocity */,
@@ -650,6 +585,7 @@
         });
     }
 
+    /** Invoked when the container is pulled. */
     public void onPull(float deltaDistance, float displacement) {
         absorbPullDeltaDistance(PULL_MULTIPLIER * deltaDistance, PULL_MULTIPLIER * displacement);
         // Current motion spec is to actually push and not pull
@@ -679,7 +615,7 @@
         mHeaderPaint.setColor(mHeaderColor);
         mHeaderPaint.setAlpha((int) (getAlpha() * Color.alpha(mHeaderColor)));
         if (mHeaderPaint.getColor() != mScrimColor && mHeaderPaint.getColor() != 0) {
-            int bottom = (int) (mSearchContainer.getBottom() + getTranslationY());
+            int bottom = getHeaderBottom();
             canvas.drawRect(0, 0, canvas.getWidth(), bottom, mHeaderPaint);
             int tabsHeight = getFloatingHeaderView().getPeripheralProtectionHeight();
             if (mTabsProtectionAlpha > 0 && tabsHeight != 0) {
@@ -689,81 +625,18 @@
         }
     }
 
-    public class AdapterHolder {
-        public static final int MAIN = 0;
-        public static final int WORK = 1;
-
-        private final boolean mIsWork;
-        public final AllAppsGridAdapter adapter;
-        final LinearLayoutManager layoutManager;
-        final AlphabeticalAppsList appsList;
-        final Rect padding = new Rect();
-        AllAppsRecyclerView recyclerView;
-        boolean verticalFadingEdge;
-
-
-        AdapterHolder(boolean isWork) {
-            mIsWork = isWork;
-            appsList = new AlphabeticalAppsList(mLauncher, mAllAppsStore,
-                    isWork ? mWorkManager.getAdapterProvider() : null);
-
-            BaseAdapterProvider[] adapterProviders =
-                    isWork ? new BaseAdapterProvider[]{mSearchAdapterProvider,
-                            mWorkManager.getAdapterProvider()}
-                            : new BaseAdapterProvider[]{mSearchAdapterProvider};
-
-            adapter = new AllAppsGridAdapter(mLauncher, getLayoutInflater(), appsList,
-                    adapterProviders);
-            appsList.setAdapter(adapter);
-            layoutManager = adapter.getLayoutManager();
-        }
-
-        void setup(@NonNull View rv, @Nullable ItemInfoMatcher matcher) {
-            appsList.updateItemFilter(matcher);
-            recyclerView = (AllAppsRecyclerView) rv;
-            recyclerView.setEdgeEffectFactory(createEdgeEffectFactory());
-            recyclerView.setApps(appsList);
-            recyclerView.setLayoutManager(layoutManager);
-            recyclerView.setAdapter(adapter);
-            recyclerView.setHasFixedSize(true);
-            // No animations will occur when changes occur to the items in this RecyclerView.
-            recyclerView.setItemAnimator(null);
-            recyclerView.addOnScrollListener(mScrollListener);
-            FocusedItemDecorator focusedItemDecorator = new FocusedItemDecorator(recyclerView);
-            recyclerView.addItemDecoration(focusedItemDecorator);
-            adapter.setIconFocusListener(focusedItemDecorator.getFocusListener());
-            applyVerticalFadingEdgeEnabled(verticalFadingEdge);
-            applyPadding();
-            if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
-                recyclerView.addItemDecoration(mSearchAdapterProvider.getDecorator());
-            }
-        }
-
-        void applyPadding() {
-            if (recyclerView != null) {
-                int bottomOffset = 0;
-                if (mIsWork && mWorkManager.getWorkModeSwitch() != null) {
-                    bottomOffset = mInsets.bottom + mWorkManager.getWorkModeSwitch().getHeight();
-                }
-                recyclerView.setPadding(padding.left, padding.top, padding.right,
-                        padding.bottom + bottomOffset);
-            }
-        }
-
-        public void applyVerticalFadingEdgeEnabled(boolean enabled) {
-            verticalFadingEdge = enabled;
-            mAH[AdapterHolder.MAIN].recyclerView.setVerticalFadingEdgeEnabled(!mUsingTabs
-                    && verticalFadingEdge);
+    /**
+     * redraws header protection
+     */
+    public void invalidateHeader() {
+        if (mScrimView != null && mHeader.isHeaderProtectionSupported()) {
+            mScrimView.invalidate();
         }
     }
 
-
     protected void updateHeaderScroll(int scrolledOffset) {
-
         float prog = Utilities.boundToRange((float) scrolledOffset / mHeaderThreshold, 0f, 1f);
-        int viewBG = ColorUtils.blendARGB(mScrimColor, mHeaderProtectionColor, prog);
-        int headerColor = ColorUtils.setAlphaComponent(viewBG,
-                (int) (getSearchView().getAlpha() * 255));
+        int headerColor = getHeaderColor(prog);
         int tabsAlpha = mHeader.getPeripheralProtectionHeight() == 0 ? 0
                 : (int) (Utilities.boundToRange(
                         (scrolledOffset + mHeader.mSnappedScrolledY) / mHeaderThreshold, 0f, 1f)
@@ -773,23 +646,78 @@
             mTabsProtectionAlpha = tabsAlpha;
             invalidateHeader();
         }
-        if (mSearchUiManager.getEditText() != null) {
-            boolean bgVisible = mSearchUiManager.getBackgroundVisibility();
-            if (scrolledOffset == 0 && !mIsSearching) {
-                bgVisible = true;
-            } else if (scrolledOffset > mHeaderThreshold) {
-                bgVisible = false;
-            }
-            mSearchUiManager.setBackgroundVisibility(bgVisible, 1 - prog);
-        }
     }
 
-    /**
-     * redraws header protection
-     */
-    public void invalidateHeader() {
-        if (mScrimView != null && mHeader.isHeaderProtectionSupported()) {
-            mScrimView.invalidate();
+    protected int getHeaderColor(float blendRatio) {
+        return ColorUtils.blendARGB(mScrimColor, mHeaderProtectionColor, blendRatio);
+    }
+
+    protected int getHeaderBottom() {
+        return (int) getTranslationY();
+    }
+
+    /** Holds a {@link AllAppsGridAdapter} and related fields. */
+    public class AdapterHolder {
+        public static final int MAIN = 0;
+        public static final int WORK = 1;
+
+        private final boolean mIsWork;
+        public final AllAppsGridAdapter<T> adapter;
+        final LinearLayoutManager mLayoutManager;
+        final AlphabeticalAppsList<T> mAppsList;
+        final Rect mPadding = new Rect();
+        AllAppsRecyclerView mRecyclerView;
+        boolean mVerticalFadingEdge;
+
+        AdapterHolder(boolean isWork) {
+            mIsWork = isWork;
+            mAppsList = new AlphabeticalAppsList<>(mActivityContext, mAllAppsStore,
+                    isWork ? mWorkManager.getAdapterProvider() : null);
+
+            BaseAdapterProvider[] adapterProviders =
+                    isWork ? new BaseAdapterProvider[]{mMainAdapterProvider,
+                            mWorkManager.getAdapterProvider()}
+                            : new BaseAdapterProvider[]{mMainAdapterProvider};
+
+            adapter = new AllAppsGridAdapter<>(mActivityContext, getLayoutInflater(), mAppsList,
+                    adapterProviders);
+            mAppsList.setAdapter(adapter);
+            mLayoutManager = adapter.getLayoutManager();
+        }
+
+        void setup(@NonNull View rv, @Nullable ItemInfoMatcher matcher) {
+            mAppsList.updateItemFilter(matcher);
+            mRecyclerView = (AllAppsRecyclerView) rv;
+            mRecyclerView.setEdgeEffectFactory(createEdgeEffectFactory());
+            mRecyclerView.setApps(mAppsList);
+            mRecyclerView.setLayoutManager(mLayoutManager);
+            mRecyclerView.setAdapter(adapter);
+            mRecyclerView.setHasFixedSize(true);
+            // No animations will occur when changes occur to the items in this RecyclerView.
+            mRecyclerView.setItemAnimator(null);
+            mRecyclerView.addOnScrollListener(mScrollListener);
+            FocusedItemDecorator focusedItemDecorator = new FocusedItemDecorator(mRecyclerView);
+            mRecyclerView.addItemDecoration(focusedItemDecorator);
+            adapter.setIconFocusListener(focusedItemDecorator.getFocusListener());
+            applyVerticalFadingEdgeEnabled(mVerticalFadingEdge);
+            applyPadding();
+        }
+
+        void applyPadding() {
+            if (mRecyclerView != null) {
+                int bottomOffset = 0;
+                if (mIsWork && mWorkManager.getWorkModeSwitch() != null) {
+                    bottomOffset = mInsets.bottom + mWorkManager.getWorkModeSwitch().getHeight();
+                }
+                mRecyclerView.setPadding(mPadding.left, mPadding.top, mPadding.right,
+                        mPadding.bottom + bottomOffset);
+            }
+        }
+
+        private void applyVerticalFadingEdgeEnabled(boolean enabled) {
+            mVerticalFadingEdge = enabled;
+            mAH.get(AdapterHolder.MAIN).mRecyclerView.setVerticalFadingEdgeEnabled(!mUsingTabs
+                    && mVerticalFadingEdge);
         }
     }
 }
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index 1f7822d..059d4b8 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -41,6 +41,7 @@
 import com.android.systemui.plugins.PluginListener;
 
 import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 
 public class FloatingHeaderView extends LinearLayout implements
@@ -72,7 +73,8 @@
                     moved(current);
                     applyVerticalMove();
                     if (headerCollapsed != mHeaderCollapsed) {
-                        AllAppsContainerView parent = (AllAppsContainerView) getParent();
+                        BaseAllAppsContainerView<?> parent =
+                                (BaseAllAppsContainerView<?>) getParent();
                         parent.invalidateHeader();
                     }
                 }
@@ -195,7 +197,7 @@
         updateExpectedHeight();
 
         if (mMaxTranslation != oldMaxHeight) {
-            AllAppsContainerView parent = (AllAppsContainerView) getParent();
+            BaseAllAppsContainerView<?> parent = (BaseAllAppsContainerView<?>) getParent();
             if (parent != null) {
                 parent.setupHeader();
             }
@@ -224,7 +226,8 @@
         return super.getFocusedChild();
     }
 
-    public void setup(AllAppsContainerView.AdapterHolder[] mAH, boolean tabsHidden) {
+    <T extends Context & ActivityContext> void setup(
+            List<BaseAllAppsContainerView<T>.AdapterHolder> mAH, boolean tabsHidden) {
         for (FloatingHeaderRow row : mAllRows) {
             row.setup(this, mAllRows, tabsHidden);
         }
@@ -232,8 +235,10 @@
 
         mTabsHidden = tabsHidden;
         mTabLayout.setVisibility(tabsHidden ? View.GONE : View.VISIBLE);
-        mMainRV = setupRV(mMainRV, mAH[AllAppsContainerView.AdapterHolder.MAIN].recyclerView);
-        mWorkRV = setupRV(mWorkRV, mAH[AllAppsContainerView.AdapterHolder.WORK].recyclerView);
+        mMainRV = setupRV(mMainRV,
+                mAH.get(BaseAllAppsContainerView.AdapterHolder.MAIN).mRecyclerView);
+        mWorkRV = setupRV(mWorkRV,
+                mAH.get(BaseAllAppsContainerView.AdapterHolder.WORK).mRecyclerView);
         mParent = (ViewGroup) mMainRV.getParent();
         setMainActive(mMainRVActive || mWorkRV == null);
         reset(false);
diff --git a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
index b6dcec6..30d33f9 100644
--- a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
@@ -26,9 +26,7 @@
 /**
  * AllAppsContainerView with launcher specific callbacks
  */
-public class LauncherAllAppsContainerView extends AllAppsContainerView {
-
-    private final Launcher mLauncher;
+public class LauncherAllAppsContainerView extends ActivityAllAppsContainerView<Launcher> {
 
     public LauncherAllAppsContainerView(Context context) {
         this(context, null);
@@ -40,14 +38,13 @@
 
     public LauncherAllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-        mLauncher = Launcher.getLauncher(context);
     }
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         // The AllAppsContainerView houses the QSB and is hence visible from the Workspace
         // Overview states. We shouldn't intercept for the scrubber in these cases.
-        if (!mLauncher.isInState(LauncherState.ALL_APPS)) {
+        if (!mActivityContext.isInState(LauncherState.ALL_APPS)) {
             mTouchHandler = null;
             return false;
         }
@@ -57,7 +54,7 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
-        if (!mLauncher.isInState(LauncherState.ALL_APPS)) {
+        if (!mActivityContext.isInState(LauncherState.ALL_APPS)) {
             return false;
         }
         return super.onTouchEvent(ev);
@@ -66,13 +63,8 @@
     @Override
     public void setInsets(Rect insets) {
         super.setInsets(insets);
-        int allAppsStartingPositionY = mLauncher.getDeviceProfile().availableHeightPx
-                - mLauncher.getDeviceProfile().allAppsOpenVerticalTranslate;
-        mLauncher.getAllAppsController().setScrollRangeDelta(allAppsStartingPositionY);
-    }
-
-    @Override
-    public void onActivePageChanged(int currentActivePage) {
-        super.onActivePageChanged(currentActivePage);
+        int allAppsStartingPositionY = mActivityContext.getDeviceProfile().availableHeightPx
+                - mActivityContext.getDeviceProfile().allAppsOpenVerticalTranslate;
+        mActivityContext.getAllAppsController().setScrollRangeDelta(allAppsStartingPositionY);
     }
 }
diff --git a/src/com/android/launcher3/allapps/SearchUiManager.java b/src/com/android/launcher3/allapps/SearchUiManager.java
index 7478b53..f9055ee 100644
--- a/src/com/android/launcher3/allapps/SearchUiManager.java
+++ b/src/com/android/launcher3/allapps/SearchUiManager.java
@@ -29,7 +29,7 @@
     /**
      * Initializes the search manager.
      */
-    void initializeSearch(AllAppsContainerView containerView);
+    void initializeSearch(ActivityAllAppsContainerView<?> containerView);
 
     /**
      * Notifies the search manager to close any active search session.
diff --git a/src/com/android/launcher3/allapps/WorkEduCard.java b/src/com/android/launcher3/allapps/WorkEduCard.java
index 9db7bf0..c336496 100644
--- a/src/com/android/launcher3/allapps/WorkEduCard.java
+++ b/src/com/android/launcher3/allapps/WorkEduCard.java
@@ -23,16 +23,18 @@
 import android.view.animation.AnimationUtils;
 import android.widget.FrameLayout;
 
-import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.views.ActivityContext;
 
 /**
  * Work profile toggle switch shown at the bottom of AllApps work tab
  */
-public class WorkEduCard extends FrameLayout implements View.OnClickListener,
+public class WorkEduCard extends FrameLayout implements
+        View.OnClickListener,
         Animation.AnimationListener {
 
-    private final Launcher mLauncher;
+    private final ActivityContext mActivityContext;
     Animation mDismissAnim;
     private int mPosition = -1;
 
@@ -46,7 +48,7 @@
 
     public WorkEduCard(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-        mLauncher = Launcher.getLauncher(getContext());
+        mActivityContext = ActivityContext.lookupContext(getContext());
         mDismissAnim = AnimationUtils.loadAnimation(context, android.R.anim.fade_out);
         mDismissAnim.setDuration(500);
         mDismissAnim.setAnimationListener(this);
@@ -69,13 +71,14 @@
         super.onFinishInflate();
         findViewById(R.id.action_btn).setOnClickListener(this);
         MarginLayoutParams lp = ((MarginLayoutParams) findViewById(R.id.wrapper).getLayoutParams());
-        lp.width = mLauncher.getAppsView().getActiveRecyclerView().getTabWidth();
+        lp.width = mActivityContext.getAppsView().getActiveRecyclerView().getTabWidth();
     }
 
     @Override
     public void onClick(View view) {
         startAnimation(mDismissAnim);
-        mLauncher.getSharedPrefs().edit().putInt(WorkAdapterProvider.KEY_WORK_EDU_STEP, 1).apply();
+        Utilities.getPrefs(getContext()).edit().putInt(WorkAdapterProvider.KEY_WORK_EDU_STEP,
+                1).apply();
     }
 
     @Override
@@ -97,8 +100,8 @@
         if (mPosition == -1) {
             if (getParent() != null) ((ViewGroup) getParent()).removeView(WorkEduCard.this);
         } else {
-            AllAppsRecyclerView rv = mLauncher.getAppsView()
-                    .mAH[AllAppsContainerView.AdapterHolder.WORK].recyclerView;
+            AllAppsRecyclerView rv = mActivityContext.getAppsView().mAH.get(
+                    ActivityAllAppsContainerView.AdapterHolder.WORK).mRecyclerView;
             rv.getApps().getAdapterItems().remove(mPosition);
             rv.getAdapter().notifyItemRemoved(mPosition);
         }
diff --git a/src/com/android/launcher3/allapps/WorkModeSwitch.java b/src/com/android/launcher3/allapps/WorkModeSwitch.java
index be01581..4598690 100644
--- a/src/com/android/launcher3/allapps/WorkModeSwitch.java
+++ b/src/com/android/launcher3/allapps/WorkModeSwitch.java
@@ -26,12 +26,11 @@
 import android.view.WindowInsets;
 import android.widget.Button;
 
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Insettable;
-import com.android.launcher3.Launcher;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.KeyboardInsetAnimationCallback;
+import com.android.launcher3.views.ActivityContext;
 import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip;
 
 /**
@@ -73,7 +72,7 @@
                     new KeyboardInsetAnimationCallback(this);
             setWindowInsetsAnimationCallback(keyboardInsetAnimationCallback);
         }
-        DeviceProfile grid = BaseDraggingActivity.fromContext(getContext()).getDeviceProfile();
+        DeviceProfile grid = ActivityContext.lookupContext(getContext()).getDeviceProfile();
         setInsets(grid.getInsets());
     }
 
@@ -91,7 +90,7 @@
 
     @Override
     public void onActivePageChanged(int page) {
-        mOnWorkTab = page == AllAppsContainerView.AdapterHolder.WORK;
+        mOnWorkTab = page == ActivityAllAppsContainerView.AdapterHolder.WORK;
         updateVisibility();
     }
 
@@ -99,9 +98,9 @@
     public void onClick(View view) {
         if (Utilities.ATLEAST_P && isEnabled()) {
             setFlag(FLAG_PROFILE_TOGGLE_ONGOING);
-            Launcher launcher = Launcher.getLauncher(getContext());
-            launcher.getStatsLogManager().logger().log(LAUNCHER_TURN_OFF_WORK_APPS_TAP);
-            launcher.getAppsView().getWorkManager().setWorkProfileEnabled(false);
+            ActivityContext activityContext = ActivityContext.lookupContext(getContext());
+            activityContext.getStatsLogManager().logger().log(LAUNCHER_TURN_OFF_WORK_APPS_TAP);
+            activityContext.getAppsView().getWorkManager().setWorkProfileEnabled(false);
         }
     }
 
diff --git a/src/com/android/launcher3/allapps/WorkPausedCard.java b/src/com/android/launcher3/allapps/WorkPausedCard.java
index 7593ca7..729622f 100644
--- a/src/com/android/launcher3/allapps/WorkPausedCard.java
+++ b/src/com/android/launcher3/allapps/WorkPausedCard.java
@@ -24,16 +24,16 @@
 import android.widget.Button;
 import android.widget.LinearLayout;
 
-import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.views.ActivityContext;
 
 /**
  * Work profile toggle switch shown at the bottom of AllApps work tab
  */
 public class WorkPausedCard extends LinearLayout implements View.OnClickListener {
 
-    private final Launcher mLauncher;
+    private final ActivityContext mActivityContext;
     private Button mBtn;
 
     public WorkPausedCard(Context context) {
@@ -46,7 +46,7 @@
 
     public WorkPausedCard(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-        mLauncher = Launcher.getLauncher(getContext());
+        mActivityContext = ActivityContext.lookupContext(getContext());
     }
 
 
@@ -61,8 +61,8 @@
     public void onClick(View view) {
         if (Utilities.ATLEAST_P) {
             setEnabled(false);
-            mLauncher.getAppsView().getWorkManager().setWorkProfileEnabled(true);
-            mLauncher.getStatsLogManager().logger().log(LAUNCHER_TURN_ON_WORK_APPS_TAP);
+            mActivityContext.getAppsView().getWorkManager().setWorkProfileEnabled(true);
+            mActivityContext.getStatsLogManager().logger().log(LAUNCHER_TURN_ON_WORK_APPS_TAP);
         }
     }
 
diff --git a/src/com/android/launcher3/allapps/WorkProfileManager.java b/src/com/android/launcher3/allapps/WorkProfileManager.java
index e223248..bcaf1f4 100644
--- a/src/com/android/launcher3/allapps/WorkProfileManager.java
+++ b/src/com/android/launcher3/allapps/WorkProfileManager.java
@@ -39,7 +39,8 @@
 import java.lang.annotation.RetentionPolicy;
 
 /**
- * Companion class for {@link AllAppsContainerView} to manage work tab and personal tab related
+ * Companion class for {@link BaseAllAppsContainerView} to manage work tab and personal tab
+ * related
  * logic based on {@link WorkProfileState}?
  */
 public class WorkProfileManager implements PersonalWorkSlidingTabStrip.OnActivePageChangedListener {
@@ -50,7 +51,6 @@
     public static final int STATE_DISABLED = 2;
     public static final int STATE_TRANSITION = 3;
 
-
     private final UserManager mUserManager;
 
     /**
@@ -65,7 +65,7 @@
     public @interface WorkProfileState {
     }
 
-    private final AllAppsContainerView mAllApps;
+    private final BaseAllAppsContainerView<?> mAllApps;
     private final WorkAdapterProvider mAdapterProvider;
     private final ItemInfoMatcher mMatcher;
 
@@ -75,7 +75,7 @@
     private int mCurrentState;
 
 
-    public WorkProfileManager(UserManager userManager, AllAppsContainerView allApps,
+    public WorkProfileManager(UserManager userManager, BaseAllAppsContainerView<?> allApps,
             SharedPreferences preferences) {
         mUserManager = userManager;
         mAllApps = allApps;
@@ -118,7 +118,7 @@
         mCurrentState = currentState;
         mAdapterProvider.updateCurrentState(currentState);
         if (getAH() != null) {
-            getAH().appsList.updateAdapterItems();
+            getAH().mAppsList.updateAdapterItems();
         }
         if (mWorkModeSwitch != null) {
             mWorkModeSwitch.updateCurrentState(currentState == STATE_ENABLED);
@@ -126,7 +126,7 @@
     }
 
     /**
-     * Creates and attaches for profile toggle button to {@link AllAppsContainerView}
+     * Creates and attaches for profile toggle button to {@link BaseAllAppsContainerView}
      */
     public boolean attachWorkModeSwitch() {
         if (!mAllApps.getAppsStore().hasModelFlag(
@@ -149,7 +149,7 @@
     }
 
     /**
-     * Removes work profile toggle button from {@link AllAppsContainerView}
+     * Removes work profile toggle button from {@link BaseAllAppsContainerView}
      */
     public void detachWorkModeSwitch() {
         if (mWorkModeSwitch != null && mWorkModeSwitch.getParent() == mAllApps) {
@@ -172,8 +172,8 @@
         return mWorkModeSwitch;
     }
 
-    private AllAppsContainerView.AdapterHolder getAH() {
-        return mAllApps.mAH[AllAppsContainerView.AdapterHolder.WORK];
+    private BaseAllAppsContainerView<?>.AdapterHolder getAH() {
+        return mAllApps.mAH.get(BaseAllAppsContainerView.AdapterHolder.WORK);
     }
 
     public int getCurrentState() {
diff --git a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
index 4c5a9e6..ffc049b 100644
--- a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
+++ b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
@@ -37,7 +37,7 @@
 import com.android.launcher3.ExtendedEditText;
 import com.android.launcher3.Insettable;
 import com.android.launcher3.R;
-import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
 import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
 import com.android.launcher3.allapps.AllAppsStore;
 import com.android.launcher3.allapps.AlphabeticalAppsList;
@@ -57,8 +57,8 @@
     private final AllAppsSearchBarController mSearchBarController;
     private final SpannableStringBuilder mSearchQueryBuilder;
 
-    private AlphabeticalAppsList mApps;
-    private AllAppsContainerView mAppsView;
+    private AlphabeticalAppsList<?> mApps;
+    private ActivityAllAppsContainerView<?> mAppsView;
 
     // The amount of pixels to shift down and overlap with the rest of the content.
     private final int mContentOverlap;
@@ -130,7 +130,7 @@
     }
 
     @Override
-    public void initializeSearch(AllAppsContainerView appsView) {
+    public void initializeSearch(ActivityAllAppsContainerView<?> appsView) {
         mApps = appsView.getApps();
         mAppsView = appsView;
         mSearchBarController.initialize(
diff --git a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
index 7abd555..2fe4915 100644
--- a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
+++ b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
@@ -25,21 +25,19 @@
 
 import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.BubbleTextView;
-import com.android.launcher3.allapps.AllAppsContainerView;
 import com.android.launcher3.allapps.AllAppsGridAdapter;
 import com.android.launcher3.model.data.ItemInfo;
 
 /**
  * Provides views for local search results
  */
-public class DefaultSearchAdapterProvider extends SearchAdapterProvider {
+public class DefaultSearchAdapterProvider extends SearchAdapterProvider<BaseDraggingActivity> {
 
     private final RecyclerView.ItemDecoration mDecoration;
     private View mHighlightedView;
 
-    public DefaultSearchAdapterProvider(BaseDraggingActivity launcher,
-            AllAppsContainerView appsContainerView) {
-        super(launcher, appsContainerView);
+    public DefaultSearchAdapterProvider(BaseDraggingActivity launcher) {
+        super(launcher);
         mDecoration = new RecyclerView.ItemDecoration() {
             @Override
             public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent,
diff --git a/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java b/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
index 7af0406..bc52784 100644
--- a/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
+++ b/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
@@ -21,18 +21,19 @@
 
 import androidx.recyclerview.widget.RecyclerView;
 
-import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.allapps.AllAppsContainerView;
 import com.android.launcher3.allapps.BaseAdapterProvider;
+import com.android.launcher3.views.ActivityContext;
 
 /**
  * A UI expansion wrapper providing for search results
+ *
+ * @param <T> Context for this adapter provider.
  */
-public abstract class SearchAdapterProvider extends BaseAdapterProvider {
+public abstract class SearchAdapterProvider<T extends ActivityContext> extends BaseAdapterProvider {
 
-    protected final BaseDraggingActivity mLauncher;
+    protected final T mLauncher;
 
-    public SearchAdapterProvider(BaseDraggingActivity launcher, AllAppsContainerView appsView) {
+    public SearchAdapterProvider(T launcher) {
         mLauncher = launcher;
     }
 
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 98be72a..7c665c6 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -55,7 +55,7 @@
 import com.android.launcher3.Reorderable;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.Workspace;
-import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
 import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.dot.FolderDotInfo;
@@ -397,7 +397,7 @@
             float finalScale = scale * scaleRelativeToDragLayer;
 
             // Account for potentially different icon sizes with non-default grid settings
-            if (d.dragSource instanceof AllAppsContainerView) {
+            if (d.dragSource instanceof ActivityAllAppsContainerView) {
                 DeviceProfile grid = mActivity.getDeviceProfile();
                 float containerScale = (1f * grid.iconSizePx / grid.allAppsIconSizePx);
                 finalScale *= containerScale;
diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
index 1a96c23..cba0655 100644
--- a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
+++ b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
@@ -30,7 +30,7 @@
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.LauncherModel;
 import com.android.launcher3.R;
-import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
 import com.android.launcher3.model.BgDataModel;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.ItemInfo;
@@ -52,7 +52,8 @@
     private LauncherModel mModel;
 
     private BaseDragLayer mDragLayer;
-    private AllAppsContainerView mAppsView;
+    // TODO(b/216191717): Verify all apps works on secondary display.
+    private ActivityAllAppsContainerView<SecondaryDisplayLauncher> mAppsView;
     private View mAppsButton;
 
     private PopupDataProvider mPopupDataProvider;
@@ -143,7 +144,8 @@
         return mAppDrawerShown;
     }
 
-    public AllAppsContainerView getAppsView() {
+    @Override
+    public ActivityAllAppsContainerView<SecondaryDisplayLauncher> getAppsView() {
         return mAppsView;
     }
 
diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java b/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
index 0d8602f..967f2c8 100644
--- a/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
+++ b/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
@@ -30,7 +30,7 @@
 import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
-import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.popup.PopupContainerWithArrow;
 import com.android.launcher3.popup.PopupDataProvider;
@@ -47,7 +47,7 @@
 public class SecondaryDragLayer extends BaseDragLayer<SecondaryDisplayLauncher> {
 
     private View mAllAppsButton;
-    private AllAppsContainerView mAppsView;
+    private ActivityAllAppsContainerView<SecondaryDisplayLauncher> mAppsView;
 
     private GridView mWorkspace;
     private PinnedAppsAdapter mPinnedAppsAdapter;
diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java
index c0f6316..8b48bae 100644
--- a/src/com/android/launcher3/views/ActivityContext.java
+++ b/src/com/android/launcher3/views/ActivityContext.java
@@ -25,6 +25,7 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.allapps.BaseAllAppsContainerView;
 import com.android.launcher3.dot.DotInfo;
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.folder.FolderIcon;
@@ -93,6 +94,13 @@
      */
     BaseDragLayer getDragLayer();
 
+    /**
+     * The all apps container, if it exists in this context.
+     */
+    default BaseAllAppsContainerView<?> getAppsView() {
+        return null;
+    }
+
     DeviceProfile getDeviceProfile();
 
     default ViewCache getViewCache() {