Support Agassi (Search Engine choice) in Android R

Test:
1) set your preferred search provider using `adb shell settings put global SEARCH_PROVIDER_PACKAGE_NAME <value>`.(eg: com.duckduckgo.mobile.android)
2) install the package name and confirm search widget on launcher is updated
3) uninstalled the package and confirm widget is replaced with placeholder on launcher.

Bug:137653564
Change-Id: I8904d5915a8c03ea6068fb5950af15ca786b8ad7
diff --git a/src/com/android/launcher3/qsb/QsbContainerView.java b/src/com/android/launcher3/qsb/QsbContainerView.java
index 857ea05..09c6c36 100644
--- a/src/com/android/launcher3/qsb/QsbContainerView.java
+++ b/src/com/android/launcher3/qsb/QsbContainerView.java
@@ -32,12 +32,15 @@
 import android.content.Intent;
 import android.graphics.Rect;
 import android.os.Bundle;
+import android.provider.Settings;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
+import androidx.annotation.Nullable;
+
 import com.android.launcher3.AppWidgetResizeFrame;
 import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.LauncherAppState;
@@ -55,6 +58,8 @@
  */
 public class QsbContainerView extends FrameLayout {
 
+    public static final String SEARCH_PROVIDER_SETTINGS_KEY = "SEARCH_PROVIDER_PACKAGE_NAME";
+
     public QsbContainerView(Context context) {
         super(context);
     }
@@ -101,7 +106,7 @@
 
         protected QsbWidgetHost createHost() {
             return new QsbWidgetHost(getContext(), QSB_WIDGET_HOST_ID,
-                    (c) -> new QsbWidgetHostView(c));
+                    (c) -> new QsbWidgetHostView(c), this::rebindFragment);
         }
 
         private FrameLayout mWrapper;
@@ -111,7 +116,6 @@
                 LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
 
             mWrapper = new FrameLayout(getContext());
-
             // Only add the view when enabled
             if (isQsbEnabled()) {
                 mWrapper.addView(createQsb(mWrapper));
@@ -247,20 +251,36 @@
         }
 
         /**
+         * returns the package name string from global settings or from system search service.
+         *
+         * @return String (package name) or null if neither exist
+         */
+        @Nullable
+        protected String getSearchProviderPackageName() {
+            String providerPkg = Settings.Global.getString(getContext().getContentResolver(),
+                    SEARCH_PROVIDER_SETTINGS_KEY);
+            if (providerPkg == null) {
+                SearchManager searchManager = getContext().getSystemService(SearchManager.class);
+                ComponentName componentName = searchManager.getGlobalSearchActivity();
+                if (componentName != null) {
+                    providerPkg = searchManager.getGlobalSearchActivity().getPackageName();
+                }
+            }
+            return providerPkg;
+        }
+
+        /**
          * Returns a widget with category {@link AppWidgetProviderInfo#WIDGET_CATEGORY_SEARCHBOX}
-         * provided by the same package which is set to be global search activity.
+         * provided by the package from getSearchProviderPackageName
          * If widgetCategory is not supported, or no such widget is found, returns the first widget
          * provided by the package.
          */
         protected AppWidgetProviderInfo getSearchWidgetProvider() {
-            SearchManager searchManager =
-                    (SearchManager) getContext().getSystemService(Context.SEARCH_SERVICE);
-            ComponentName searchComponent = searchManager.getGlobalSearchActivity();
-            if (searchComponent == null) return null;
-            String providerPkg = searchComponent.getPackageName();
-
+            String providerPkg = getSearchProviderPackageName();
+            if (providerPkg == null) {
+                return null;
+            }
             AppWidgetProviderInfo defaultWidgetForSearchPackage = null;
-
             AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getContext());
             for (AppWidgetProviderInfo info : appWidgetManager.getInstalledProviders()) {
                 if (info.provider.getPackageName().equals(providerPkg) && info.configure == null) {
@@ -279,10 +299,17 @@
     public static class QsbWidgetHost extends AppWidgetHost {
 
         private final WidgetViewFactory mViewFactory;
+        private final WidgetProvidersUpdateCallback mWidgetsUpdateCallback;
 
-        public QsbWidgetHost(Context context, int hostId, WidgetViewFactory viewFactory) {
+        public QsbWidgetHost(Context context, int hostId, WidgetViewFactory viewFactory,
+                WidgetProvidersUpdateCallback widgetProvidersUpdateCallback) {
             super(context, hostId);
             mViewFactory = viewFactory;
+            mWidgetsUpdateCallback = widgetProvidersUpdateCallback;
+        }
+
+        public QsbWidgetHost(Context context, int hostId, WidgetViewFactory viewFactory) {
+            this(context, hostId, viewFactory, null);
         }
 
         @Override
@@ -290,6 +317,14 @@
                 Context context, int appWidgetId, AppWidgetProviderInfo appWidget) {
             return mViewFactory.newView(context);
         }
+
+        @Override
+        protected void onProvidersChanged() {
+            super.onProvidersChanged();
+            if (mWidgetsUpdateCallback != null) {
+                mWidgetsUpdateCallback.onProvidersUpdated();
+            }
+        }
     }
 
     public interface WidgetViewFactory {
@@ -298,6 +333,17 @@
     }
 
     /**
+     * Callback interface for packages list update.
+     */
+    @FunctionalInterface
+    public interface WidgetProvidersUpdateCallback {
+        /**
+         * Gets called when widget providers list changes
+         */
+        void onProvidersUpdated();
+    }
+
+    /**
      * Returns true if {@param original} contains all entries defined in {@param updates} and
      * have the same value.
      * The comparison uses {@link Object#equals(Object)} to compare the values.