diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index 6097b0682da..83c229e3365 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -162,6 +162,12 @@ public class SettingsActivity extends SettingsBaseActivity public static final String EXTRA_SHOW_FRAGMENT_TAB = ":settings:show_fragment_tab"; + /** + * Whether the settings homepage activity is initiated from a search result deeplink. + */ + public static final String EXTRA_IS_DEEPLINK_HOME_STARTED_FROM_SEARCH = + ":settings:is_deeplink_home_started_from_search"; + public static final String META_DATA_KEY_FRAGMENT_CLASS = "com.android.settings.FRAGMENT_CLASS"; diff --git a/src/com/android/settings/activityembedding/EmbeddedDeepLinkUtils.kt b/src/com/android/settings/activityembedding/EmbeddedDeepLinkUtils.kt index 9bbb723af60..0878b8932c9 100644 --- a/src/com/android/settings/activityembedding/EmbeddedDeepLinkUtils.kt +++ b/src/com/android/settings/activityembedding/EmbeddedDeepLinkUtils.kt @@ -24,7 +24,9 @@ import android.content.pm.UserInfo import android.provider.Settings import android.util.Log import com.android.settings.SettingsActivity +import com.android.settings.SettingsActivity.EXTRA_IS_DEEPLINK_HOME_STARTED_FROM_SEARCH import com.android.settings.Utils +import com.android.settings.flags.Flags import com.android.settings.homepage.DeepLinkHomepageActivityInternal import com.android.settings.homepage.SettingsHomepageActivity import com.android.settings.password.PasswordUtils @@ -94,6 +96,28 @@ object EmbeddedDeepLinkUtils { } } + /** + * Returns the deep link trampoline intent for settings search results for large screen devices. + */ + @JvmStatic + fun getTrampolineIntentForSearchResult( + context: Context, + intent: Intent, + highlightMenuKey: String? + ): Intent { + return getTrampolineIntent(intent, highlightMenuKey).apply { + if (Flags.settingsSearchResultDeepLinkInSameTask()) { + // Ensure the deep link intent does not include FLAG_ACTIVITY_NEW_TASK which + // causes the search result deep link to open in a separate window. + removeFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + putExtra(EXTRA_IS_DEEPLINK_HOME_STARTED_FROM_SEARCH, true) + } else { + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) + } + + setClass(context, DeepLinkHomepageActivityInternal::class.java) + } + } /** * Returns whether the user is a sub profile. diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java index 08acbc74c7e..cf9dc6d2106 100644 --- a/src/com/android/settings/homepage/SettingsHomepageActivity.java +++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java @@ -20,6 +20,7 @@ import static android.provider.Settings.ACTION_SETTINGS_EMBED_DEEP_LINK_ACTIVITY import static android.provider.Settings.EXTRA_SETTINGS_EMBEDDED_DEEP_LINK_HIGHLIGHT_MENU_KEY; import static android.provider.Settings.EXTRA_SETTINGS_EMBEDDED_DEEP_LINK_INTENT_URI; +import static com.android.settings.SettingsActivity.EXTRA_IS_DEEPLINK_HOME_STARTED_FROM_SEARCH; import static com.android.settings.SettingsActivity.EXTRA_USER_HANDLE; import android.animation.LayoutTransition; @@ -232,7 +233,9 @@ public class SettingsHomepageActivity extends FragmentActivity implements } } - if (!isTaskRoot) { + final boolean isDeepLinkStartedFromSearch = getIntent().getBooleanExtra( + EXTRA_IS_DEEPLINK_HOME_STARTED_FROM_SEARCH, false /* defaultValue */); + if (!isTaskRoot && !isDeepLinkStartedFromSearch) { if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { Log.i(TAG, "Activity has been started, finishing"); } else { diff --git a/src/com/android/settings/search/SearchResultTrampoline.java b/src/com/android/settings/search/SearchResultTrampoline.java index 04d9db56eb7..c40402e4795 100644 --- a/src/com/android/settings/search/SearchResultTrampoline.java +++ b/src/com/android/settings/search/SearchResultTrampoline.java @@ -19,6 +19,7 @@ package com.android.settings.search; import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS; import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB; import static com.android.settings.activityembedding.EmbeddedDeepLinkUtils.getTrampolineIntent; +import static com.android.settings.activityembedding.EmbeddedDeepLinkUtils.getTrampolineIntentForSearchResult; import android.app.Activity; import android.content.Intent; @@ -35,7 +36,6 @@ import com.android.settings.SubSettings; import com.android.settings.activityembedding.ActivityEmbeddingRulesController; import com.android.settings.activityembedding.ActivityEmbeddingUtils; import com.android.settings.core.FeatureFlags; -import com.android.settings.homepage.DeepLinkHomepageActivityInternal; import com.android.settings.homepage.SettingsHomepageActivity; import com.android.settings.overlay.FeatureFactory; @@ -107,10 +107,7 @@ public class SearchResultTrampoline extends Activity { startActivity(intent); } else if (isSettingsIntelligence(callerPackage)) { if (FeatureFlagUtils.isEnabled(this, FeatureFlags.SETTINGS_SEARCH_ALWAYS_EXPAND)) { - startActivity(getTrampolineIntent(intent, highlightMenuKey) - .setClass(this, DeepLinkHomepageActivityInternal.class) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)); + startActivity(getTrampolineIntentForSearchResult(this, intent, highlightMenuKey)); } else { // Register SplitPairRule for SubSettings, set clearTop false to prevent unexpected // back navigation behavior. diff --git a/tests/spa_unit/src/com/android/settings/activityembedding/EmbeddedDeepLinkUtilsTest.kt b/tests/spa_unit/src/com/android/settings/activityembedding/EmbeddedDeepLinkUtilsTest.kt index 9a638b27ce5..1509f2f29c3 100644 --- a/tests/spa_unit/src/com/android/settings/activityembedding/EmbeddedDeepLinkUtilsTest.kt +++ b/tests/spa_unit/src/com/android/settings/activityembedding/EmbeddedDeepLinkUtilsTest.kt @@ -19,16 +19,26 @@ package com.android.settings.activityembedding import android.content.Context import android.content.Intent import android.net.Uri +import android.platform.test.annotations.DisableFlags +import android.platform.test.annotations.EnableFlags +import android.platform.test.flag.junit.SetFlagsRule import android.provider.Settings import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settings.SettingsActivity.EXTRA_IS_DEEPLINK_HOME_STARTED_FROM_SEARCH import com.android.settings.activityembedding.EmbeddedDeepLinkUtils.getTrampolineIntent +import com.android.settings.activityembedding.EmbeddedDeepLinkUtils.getTrampolineIntentForSearchResult +import com.android.settings.flags.Flags +import com.android.settings.homepage.DeepLinkHomepageActivityInternal import com.google.common.truth.Truth.assertThat +import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class EmbeddedDeepLinkUtilsTest { + @get:Rule + val setFlagsRule = SetFlagsRule() private val context: Context = ApplicationProvider.getApplicationContext() @@ -58,4 +68,72 @@ class EmbeddedDeepLinkUtilsTest { val parsedIntent = Intent.parseUri(intentUriString, Intent.URI_INTENT_SCHEME) assertThat(parsedIntent.action).isEqualTo(intent.action) } + + @Test + fun getTrampolineIntent_shouldNotHaveNewTaskFlag() { + val intent = Intent("com.android.settings.SEARCH_RESULT_TRAMPOLINE") + + val resultIntent = getTrampolineIntent(intent, "menu_key") + + val hasNewTaskFlag = (resultIntent.flags and Intent.FLAG_ACTIVITY_NEW_TASK) != 0 + assertThat(hasNewTaskFlag).isFalse() + } + + @Test + fun getTrampolineIntentForSearchResult_shouldHaveDeepLinkHomepageClass() { + val intent = Intent("com.android.settings.SEARCH_RESULT_TRAMPOLINE") + + val resultIntent = getTrampolineIntentForSearchResult(context, intent, "menu_key") + + val className = resultIntent.getComponent()!!.className + assertThat(className).isEqualTo(DeepLinkHomepageActivityInternal::class.java.name) + } + + @Test + @DisableFlags(Flags.FLAG_SETTINGS_SEARCH_RESULT_DEEP_LINK_IN_SAME_TASK) + fun getTrampolineIntentForSearchResult_shouldHaveNewTaskFlag() { + val intent = Intent("com.android.settings.SEARCH_RESULT_TRAMPOLINE") + + val resultIntent = getTrampolineIntentForSearchResult(context, intent, "menu_key") + + val hasNewTaskFlag = (resultIntent.flags and Intent.FLAG_ACTIVITY_NEW_TASK) != 0 + assertThat(hasNewTaskFlag).isTrue() + } + + @Test + @EnableFlags(Flags.FLAG_SETTINGS_SEARCH_RESULT_DEEP_LINK_IN_SAME_TASK) + fun getTrampolineIntentForSearchResult_shouldNotHaveNewTaskFlag() { + val intent = Intent("com.android.settings.SEARCH_RESULT_TRAMPOLINE") + + val resultIntent = getTrampolineIntentForSearchResult(context, intent, "menu_key") + + val hasNewTaskFlag = (resultIntent.flags and Intent.FLAG_ACTIVITY_NEW_TASK) != 0 + assertThat(hasNewTaskFlag).isFalse() + } + + @Test + @DisableFlags(Flags.FLAG_SETTINGS_SEARCH_RESULT_DEEP_LINK_IN_SAME_TASK) + fun getTrampolineIntentForSearchResult_shouldNotHaveExtraStartedFromSearch() { + val intent = Intent("com.android.settings.SEARCH_RESULT_TRAMPOLINE") + + val resultIntent = getTrampolineIntentForSearchResult(context, intent, "menu_key") + + assertThat(resultIntent.hasExtra(EXTRA_IS_DEEPLINK_HOME_STARTED_FROM_SEARCH)).isFalse() + assertThat( + resultIntent.getBooleanExtra(EXTRA_IS_DEEPLINK_HOME_STARTED_FROM_SEARCH, false) + ).isFalse() + } + + @Test + @EnableFlags(Flags.FLAG_SETTINGS_SEARCH_RESULT_DEEP_LINK_IN_SAME_TASK) + fun getTrampolineIntentForSearchResult_shouldHaveExtraStartedFromSearch() { + val intent = Intent("com.android.settings.SEARCH_RESULT_TRAMPOLINE") + + val resultIntent = getTrampolineIntentForSearchResult(context, intent, "menu_key") + + assertThat(resultIntent.hasExtra(EXTRA_IS_DEEPLINK_HOME_STARTED_FROM_SEARCH)).isTrue() + assertThat( + resultIntent.getBooleanExtra(EXTRA_IS_DEEPLINK_HOME_STARTED_FROM_SEARCH, false) + ).isTrue() + } }