Loading src/com/android/settings/SettingsActivity.java +6 −0 Original line number Diff line number Diff line Loading @@ -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"; Loading src/com/android/settings/activityembedding/EmbeddedDeepLinkUtils.kt +24 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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. Loading src/com/android/settings/homepage/SettingsHomepageActivity.java +4 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 { Loading src/com/android/settings/search/SearchResultTrampoline.java +2 −5 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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. Loading tests/spa_unit/src/com/android/settings/activityembedding/EmbeddedDeepLinkUtilsTest.kt +78 −0 Original line number Diff line number Diff line Loading @@ -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() Loading Loading @@ -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() } } Loading
src/com/android/settings/SettingsActivity.java +6 −0 Original line number Diff line number Diff line Loading @@ -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"; Loading
src/com/android/settings/activityembedding/EmbeddedDeepLinkUtils.kt +24 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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. Loading
src/com/android/settings/homepage/SettingsHomepageActivity.java +4 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 { Loading
src/com/android/settings/search/SearchResultTrampoline.java +2 −5 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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. Loading
tests/spa_unit/src/com/android/settings/activityembedding/EmbeddedDeepLinkUtilsTest.kt +78 −0 Original line number Diff line number Diff line Loading @@ -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() Loading Loading @@ -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() } }