Add referrer when launching search intent.

Bug: 123294739
Test: robotests
Change-Id: I600abf1d764e828d52f3b8d35ad24cdc94dfba01
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 25ad73d..99eb218 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -18,6 +18,7 @@
 
 import android.app.ActionBar;
 import android.app.ActivityManager;
+import android.app.settings.SettingsEnums;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -287,7 +288,7 @@
             final Toolbar toolbar = findViewById(R.id.search_action_bar);
             setActionBar(toolbar);
             FeatureFactory.getFactory(this).getSearchFeatureProvider()
-                    .initSearchToolbar(this, toolbar);
+                    .initSearchToolbar(this, toolbar, SettingsEnums.SETTINGS_HOMEPAGE);
         }
 
         ActionBar actionBar = getActionBar();
diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java
index 9acda68..bdf4769 100644
--- a/src/com/android/settings/homepage/SettingsHomepageActivity.java
+++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.homepage;
 
+import android.app.settings.SettingsEnums;
 import android.content.Intent;
 import android.os.Bundle;
 import android.util.FeatureFlagUtils;
@@ -53,7 +54,7 @@
 
         final Toolbar toolbar = findViewById(R.id.search_action_bar);
         FeatureFactory.getFactory(this).getSearchFeatureProvider()
-                .initSearchToolbar(this /* activity */, toolbar);
+                .initSearchToolbar(this /* activity */, toolbar, SettingsEnums.SETTINGS_HOMEPAGE);
 
         final ImageView avatarView = findViewById(R.id.account_avatar);
         final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(this, avatarView);
diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java
index b98936e..dcb4acc 100644
--- a/src/com/android/settings/search/SearchFeatureProvider.java
+++ b/src/com/android/settings/search/SearchFeatureProvider.java
@@ -25,7 +25,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
-import android.provider.Settings;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Toolbar;
@@ -40,7 +39,6 @@
  */
 public interface SearchFeatureProvider {
 
-    Intent SEARCH_UI_INTENT = new Intent(Settings.ACTION_APP_SEARCH_SETTINGS);
     int REQUEST_CODE = 0;
 
     /**
@@ -64,7 +62,7 @@
     /**
      * Initializes the search toolbar.
      */
-    default void initSearchToolbar(Activity activity, Toolbar toolbar) {
+    default void initSearchToolbar(Activity activity, Toolbar toolbar, int pageId) {
         if (activity == null || toolbar == null) {
             return;
         }
@@ -87,9 +85,8 @@
         navView.setBackground(null);
 
         toolbar.setOnClickListener(tb -> {
-            final Intent intent = SEARCH_UI_INTENT;
-            intent.setPackage(getSettingsIntelligencePkgName(activity));
             final Context context = activity.getApplicationContext();
+            final Intent intent = buildSearchIntent(context, pageId);
 
             if (activity.getPackageManager().queryIntentActivities(intent,
                     PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) {
@@ -97,10 +94,12 @@
             }
 
             FeatureFactory.getFactory(context).getSlicesFeatureProvider()
-                    .indexSliceDataAsync(activity.getApplicationContext());
+                    .indexSliceDataAsync(context);
             FeatureFactory.getFactory(context).getMetricsFeatureProvider()
                     .action(context, SettingsEnums.ACTION_SEARCH_RESULTS);
             activity.startActivityForResult(intent, REQUEST_CODE);
         });
     }
+
+    Intent buildSearchIntent(Context context, int pageId);
 }
diff --git a/src/com/android/settings/search/SearchFeatureProviderImpl.java b/src/com/android/settings/search/SearchFeatureProviderImpl.java
index a5a8777..63bf420 100644
--- a/src/com/android/settings/search/SearchFeatureProviderImpl.java
+++ b/src/com/android/settings/search/SearchFeatureProviderImpl.java
@@ -19,6 +19,9 @@
 
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.provider.Settings;
 import android.text.TextUtils;
 
 import com.android.settingslib.search.SearchIndexableResources;
@@ -59,7 +62,22 @@
         return mSearchIndexableResources;
     }
 
+    @Override
+    public Intent buildSearchIntent(Context context, int pageId) {
+        return new Intent(Settings.ACTION_APP_SEARCH_SETTINGS)
+                .setPackage(getSettingsIntelligencePkgName(context))
+                .putExtra(Intent.EXTRA_REFERRER, buildReferrer(context, pageId));
+    }
+
     protected boolean isSignatureWhitelisted(Context context, String callerPackage) {
         return false;
     }
+
+    private static Uri buildReferrer(Context context, int pageId) {
+        return new Uri.Builder()
+                .scheme("android-app")
+                .authority(context.getPackageName())
+                .path(String.valueOf(pageId))
+                .build();
+    }
 }
diff --git a/src/com/android/settings/search/actionbar/SearchMenuController.java b/src/com/android/settings/search/actionbar/SearchMenuController.java
index 2f1c270..af7141e 100644
--- a/src/com/android/settings/search/actionbar/SearchMenuController.java
+++ b/src/com/android/settings/search/actionbar/SearchMenuController.java
@@ -30,11 +30,10 @@
 
 import com.android.settings.R;
 import com.android.settings.Utils;
+import com.android.settings.core.InstrumentedFragment;
+import com.android.settings.core.InstrumentedPreferenceFragment;
 import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.search.SearchFeatureProvider;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.ObservableFragment;
-import com.android.settingslib.core.lifecycle.ObservablePreferenceFragment;
 import com.android.settingslib.core.lifecycle.events.OnCreateOptionsMenu;
 
 public class SearchMenuController implements LifecycleObserver, OnCreateOptionsMenu {
@@ -42,17 +41,21 @@
     public static final String NEED_SEARCH_ICON_IN_ACTION_BAR = "need_search_icon_in_action_bar";
 
     private final Fragment mHost;
+    private final int mPageId;
 
-    public static void init(@NonNull ObservablePreferenceFragment host) {
-        host.getSettingsLifecycle().addObserver(new SearchMenuController(host));
+    public static void init(@NonNull InstrumentedPreferenceFragment host) {
+        host.getSettingsLifecycle().addObserver(
+                new SearchMenuController(host, host.getMetricsCategory()));
     }
 
-    public static void init(@NonNull ObservableFragment host) {
-        host.getSettingsLifecycle().addObserver(new SearchMenuController(host));
+    public static void init(@NonNull InstrumentedFragment host) {
+        host.getSettingsLifecycle().addObserver(
+                new SearchMenuController(host, host.getMetricsCategory()));
     }
 
-    private SearchMenuController(@NonNull Fragment host) {
+    private SearchMenuController(@NonNull Fragment host, int pageId) {
         mHost = host;
+        mPageId = pageId;
     }
 
     @Override
@@ -79,8 +82,9 @@
         searchItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
 
         searchItem.setOnMenuItemClickListener(target -> {
-            final Intent intent = SearchFeatureProvider.SEARCH_UI_INTENT;
-            intent.setPackage(SettingsIntelligencePkgName);
+            final Intent intent = FeatureFactory.getFactory(context)
+                    .getSearchFeatureProvider()
+                    .buildSearchIntent(context, mPageId);
 
             if (context.getPackageManager().queryIntentActivities(intent,
                     PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) {
diff --git a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java
index 7f709d6..444a813 100644
--- a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java
@@ -20,10 +20,12 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.app.Activity;
+import android.app.settings.SettingsEnums;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ResolveInfo;
+import android.net.Uri;
 import android.provider.Settings;
 import android.widget.Toolbar;
 
@@ -60,19 +62,19 @@
     @Test
     @Config(shadows = ShadowUtils.class)
     public void initSearchToolbar_hasResolvedInfo_shouldStartCorrectIntent() {
-        final Intent searchIntent = new Intent(SearchFeatureProvider.SEARCH_UI_INTENT)
+        final Intent searchIntent = new Intent(Settings.ACTION_APP_SEARCH_SETTINGS)
                 .setPackage(mActivity.getString(R.string.config_settingsintelligence_package_name));
         final ResolveInfo info = new ResolveInfo();
         info.activityInfo = new ActivityInfo();
         mPackageManager.addResolveInfoForIntent(searchIntent, info);
 
         // Should not crash.
-        mProvider.initSearchToolbar(mActivity, null);
+        mProvider.initSearchToolbar(mActivity, null, SettingsEnums.TESTING);
 
         final Toolbar toolbar = new Toolbar(mActivity);
         // This ensures navigationView is created.
         toolbar.setNavigationContentDescription("test");
-        mProvider.initSearchToolbar(mActivity, toolbar);
+        mProvider.initSearchToolbar(mActivity, toolbar, SettingsEnums.TESTING);
 
         toolbar.performClick();
 
@@ -87,7 +89,7 @@
         final Toolbar toolbar = new Toolbar(mActivity);
         // This ensures navigationView is created.
         toolbar.setNavigationContentDescription("test");
-        mProvider.initSearchToolbar(mActivity, toolbar);
+        mProvider.initSearchToolbar(mActivity, toolbar, SettingsEnums.TESTING);
 
         toolbar.performClick();
 
@@ -108,6 +110,15 @@
         assertThat(Shadows.shadowOf(mActivity).getNextStartedActivity()).isNull();
     }
 
+    @Test
+    public void buildSearchIntent_shouldIncludeReferrer() {
+        final Intent searchIntent = mProvider.buildSearchIntent(mActivity, SettingsEnums.TESTING);
+        final Uri referrer = searchIntent.getParcelableExtra(Intent.EXTRA_REFERRER);
+
+        assertThat(referrer.toSafeString()).isEqualTo(
+                "android-app://" + mActivity.getPackageName() + "/" + SettingsEnums.TESTING);
+    }
+
     @Test(expected = IllegalArgumentException.class)
     public void verifyLaunchSearchResultPageCaller_nullCaller_shouldCrash() {
         mProvider.verifyLaunchSearchResultPageCaller(mActivity, null /* caller */);
diff --git a/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java b/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java
index af1a82d..3063912 100644
--- a/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java
+++ b/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java
@@ -17,11 +17,11 @@
 package com.android.settings.search.actionbar;
 
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
+import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.os.Bundle;
 import android.provider.Settings.Global;
@@ -29,9 +29,9 @@
 import android.view.MenuItem;
 
 import com.android.settings.R;
+import com.android.settings.core.InstrumentedFragment;
+import com.android.settings.core.InstrumentedPreferenceFragment;
 import com.android.settings.testutils.shadow.ShadowUtils;
-import com.android.settingslib.core.lifecycle.ObservableFragment;
-import com.android.settingslib.core.lifecycle.ObservablePreferenceFragment;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -49,15 +49,24 @@
     @Mock
     private Menu mMenu;
     private TestPreferenceFragment mPreferenceHost;
-    private ObservableFragment mHost;
+    private InstrumentedFragment mHost;
     private Context mContext;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = RuntimeEnvironment.application;
-        mHost = spy(new ObservableFragment());
-        when(mHost.getContext()).thenReturn(mContext);
+        mHost = new InstrumentedFragment() {
+            @Override
+            public Context getContext() {
+                return mContext;
+            }
+
+            @Override
+            public int getMetricsCategory() {
+                return SettingsEnums.TESTING;
+            }
+        };
         mPreferenceHost = new TestPreferenceFragment();
         Global.putInt(mContext.getContentResolver(), Global.DEVICE_PROVISIONED, 1);
 
@@ -101,7 +110,7 @@
         verifyZeroInteractions(mMenu);
     }
 
-    private static class TestPreferenceFragment extends ObservablePreferenceFragment {
+    private static class TestPreferenceFragment extends InstrumentedPreferenceFragment {
         @Override
         public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
         }
@@ -110,5 +119,10 @@
         public Context getContext() {
             return RuntimeEnvironment.application;
         }
+
+        @Override
+        public int getMetricsCategory() {
+            return SettingsEnums.TESTING;
+        }
     }
 }