Let SpaBridgeActivity support HIGHLIGHT_MENU_KEY

Also the SpaAppBridgeActivity.

Could be tested by,
adb shell am start -n com.android.settings/.ManageFullScreenIntent

adb shell am start \
  -a android.settings.MANAGE_APP_USE_FULL_SCREEN_INTENT \
  -d package:com.android.settings

adb shell am start -n com.android.settings/.UsageStatsActivity

Bug: 309075424
Test: manual - on tablet
Test: unit test
Change-Id: I778443e9d21d165904e415c66c03aafc7ac81372
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 85a443e..f88c55d 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1741,6 +1741,8 @@
                         android:targetActivity=".spa.SpaBridgeActivity">
             <meta-data android:name="com.android.settings.spa.DESTINATION"
                        android:value="TogglePermissionAppList/UseFullScreenIntent"/>
+            <meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
+                android:value="@string/menu_key_apps"/>
         </activity-alias>
 
         <activity-alias android:name="AppManageFullScreenIntent"
@@ -1753,6 +1755,8 @@
             </intent-filter>
             <meta-data android:name="com.android.settings.spa.DESTINATION"
                        android:value="TogglePermissionAppInfoPage/UseFullScreenIntent"/>
+            <meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
+                android:value="@string/menu_key_apps"/>
         </activity-alias>
 
         <activity android:name=".applications.InstalledAppOpenByDefaultActivity"
@@ -4967,6 +4971,8 @@
             </intent-filter>
             <meta-data android:name="com.android.settings.spa.DESTINATION"
                        android:value="UsageStats"/>
+            <meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
+                android:value="@string/menu_key_apps"/>
         </activity-alias>
 
         <!-- [b/197780098] Disable eager initialization of Jetpack libraries. -->
diff --git a/src/com/android/settings/spa/SpaAppBridgeActivity.kt b/src/com/android/settings/spa/SpaAppBridgeActivity.kt
index 1a77442..a68d220 100644
--- a/src/com/android/settings/spa/SpaAppBridgeActivity.kt
+++ b/src/com/android/settings/spa/SpaAppBridgeActivity.kt
@@ -20,7 +20,6 @@
 import android.content.Intent
 import android.os.Bundle
 import android.os.UserHandle
-import com.android.settings.spa.SpaBridgeActivity.Companion.getDestination
 import com.android.settings.spa.SpaBridgeActivity.Companion.startSpaActivityFromBridge
 
 /**
@@ -33,11 +32,7 @@
 class SpaAppBridgeActivity : Activity() {
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
-        getDestination()?.let { destinationPrefix ->
-            getDestinationForApp(destinationPrefix, intent)?.let { destination ->
-                startSpaActivityFromBridge(destination)
-            }
-        }
+        startSpaActivityFromBridge { getDestinationForApp(it, intent) }
         finish()
     }
 
diff --git a/src/com/android/settings/spa/SpaBridgeActivity.kt b/src/com/android/settings/spa/SpaBridgeActivity.kt
index 0e239ae..61d8f51 100644
--- a/src/com/android/settings/spa/SpaBridgeActivity.kt
+++ b/src/com/android/settings/spa/SpaBridgeActivity.kt
@@ -18,12 +18,10 @@
 
 import android.app.Activity
 import android.content.Intent
-import android.content.pm.PackageManager
-import android.content.pm.PackageManager.ComponentInfoFlags
 import android.os.Bundle
-import androidx.annotation.VisibleForTesting
 import com.android.settings.activityembedding.ActivityEmbeddingUtils
 import com.android.settings.activityembedding.EmbeddedDeepLinkUtils.tryStartMultiPaneDeepLink
+import com.android.settings.spa.SpaDestination.Companion.getDestination
 import com.android.settingslib.spa.framework.util.SESSION_EXTERNAL
 import com.android.settingslib.spa.framework.util.appendSpaParams
 
@@ -37,29 +35,23 @@
 class SpaBridgeActivity : Activity() {
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
-        getDestination()?.let { destination ->
-            startSpaActivityFromBridge(destination)
-        }
+        startSpaActivityFromBridge()
         finish()
     }
 
     companion object {
-        fun Activity.startSpaActivityFromBridge(destination: String) {
+        fun Activity.startSpaActivityFromBridge(destinationFactory: (String) -> String? = { it }) {
+            val (destination, highlightMenuKey) = getDestination(destinationFactory) ?: return
             val intent = Intent(this, SpaActivity::class.java)
-                .appendSpaParams(destination = destination)
-                .appendSpaParams(sessionName = SESSION_EXTERNAL)
+                .appendSpaParams(
+                    destination = destination,
+                    sessionName = SESSION_EXTERNAL,
+                )
             if (!ActivityEmbeddingUtils.isEmbeddingActivityEnabled(this) ||
-                !tryStartMultiPaneDeepLink(intent)) {
+                !tryStartMultiPaneDeepLink(intent, highlightMenuKey)
+            ) {
                 startActivity(intent)
             }
         }
-
-        fun Activity.getDestination(): String? =
-            packageManager.getActivityInfo(
-                componentName, ComponentInfoFlags.of(PackageManager.GET_META_DATA.toLong())
-            ).metaData.getString(META_DATA_KEY_DESTINATION)
-
-        @VisibleForTesting
-        const val META_DATA_KEY_DESTINATION = "com.android.settings.spa.DESTINATION"
     }
 }
diff --git a/src/com/android/settings/spa/SpaDestination.kt b/src/com/android/settings/spa/SpaDestination.kt
new file mode 100644
index 0000000..bdec1d8
--- /dev/null
+++ b/src/com/android/settings/spa/SpaDestination.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 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.settings.spa
+
+import android.app.Activity
+import android.content.pm.PackageManager
+import androidx.annotation.VisibleForTesting
+import com.android.settings.SettingsActivity.META_DATA_KEY_HIGHLIGHT_MENU_KEY
+
+data class SpaDestination(
+    val destination: String,
+    val highlightMenuKey: String?,
+) {
+    companion object {
+        fun Activity.getDestination(
+            destinationFactory: (String) -> String? = { it },
+        ): SpaDestination? {
+            val metaData = packageManager.getActivityInfo(
+                componentName,
+                PackageManager.ComponentInfoFlags.of(PackageManager.GET_META_DATA.toLong())
+            ).metaData
+            val destination = metaData.getString(META_DATA_KEY_DESTINATION)
+            if (destination.isNullOrBlank()) return null
+            val finalDestination = destinationFactory(destination)
+            if (finalDestination.isNullOrBlank()) return null
+            return SpaDestination(
+                destination = finalDestination,
+                highlightMenuKey = metaData.getString(META_DATA_KEY_HIGHLIGHT_MENU_KEY),
+            )
+        }
+
+        @VisibleForTesting
+        const val META_DATA_KEY_DESTINATION = "com.android.settings.spa.DESTINATION"
+    }
+}
diff --git a/tests/spa_unit/src/com/android/settings/spa/SpaBridgeActivityTest.kt b/tests/spa_unit/src/com/android/settings/spa/SpaBridgeActivityTest.kt
deleted file mode 100644
index 48fa823..0000000
--- a/tests/spa_unit/src/com/android/settings/spa/SpaBridgeActivityTest.kt
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2023 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.settings.spa
-
-import android.app.Activity
-import android.content.ComponentName
-import android.content.pm.ActivityInfo
-import android.content.pm.PackageManager
-import android.content.pm.PackageManager.ComponentInfoFlags
-import androidx.core.os.bundleOf
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settings.spa.SpaBridgeActivity.Companion.META_DATA_KEY_DESTINATION
-import com.android.settings.spa.SpaBridgeActivity.Companion.getDestination
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.kotlin.any
-import org.mockito.kotlin.doReturn
-import org.mockito.kotlin.eq
-import org.mockito.kotlin.mock
-
-@RunWith(AndroidJUnit4::class)
-class SpaBridgeActivityTest {
-    private val mockPackageManager = mock<PackageManager> {
-        on { getActivityInfo(eq(COMPONENT_NAME), any<ComponentInfoFlags>()) } doReturn
-            ActivityInfo().apply {
-                metaData = bundleOf(META_DATA_KEY_DESTINATION to DESTINATION)
-            }
-    }
-
-    private val activity = mock<Activity> {
-        on { componentName } doReturn COMPONENT_NAME
-        on { packageManager } doReturn mockPackageManager
-    }
-
-    @Test
-    fun getDestination() {
-        val destination = activity.getDestination()
-
-        assertThat(destination).isEqualTo(DESTINATION)
-    }
-
-    private companion object {
-        const val PACKAGE_NAME = "package.name"
-        const val ACTIVITY_NAME = "ActivityName"
-        val COMPONENT_NAME = ComponentName(PACKAGE_NAME, ACTIVITY_NAME)
-        const val DESTINATION = "Destination"
-    }
-}
diff --git a/tests/spa_unit/src/com/android/settings/spa/SpaDestinationTest.kt b/tests/spa_unit/src/com/android/settings/spa/SpaDestinationTest.kt
new file mode 100644
index 0000000..0b9eb22
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/spa/SpaDestinationTest.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2023 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.settings.spa
+
+import android.app.Activity
+import android.content.ComponentName
+import android.content.pm.ActivityInfo
+import android.content.pm.PackageManager
+import android.os.Bundle
+import androidx.core.os.bundleOf
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.SettingsActivity.META_DATA_KEY_HIGHLIGHT_MENU_KEY
+import com.android.settings.spa.SpaDestination.Companion.META_DATA_KEY_DESTINATION
+import com.android.settings.spa.SpaDestination.Companion.getDestination
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doAnswer
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
+
+@RunWith(AndroidJUnit4::class)
+class SpaDestinationTest {
+    private var activityMetadata: Bundle = bundleOf()
+
+    private val mockPackageManager = mock<PackageManager> {
+        on {
+            getActivityInfo(
+                eq(COMPONENT_NAME),
+                any<PackageManager.ComponentInfoFlags>()
+            )
+        } doAnswer {
+            ActivityInfo().apply { metaData = activityMetadata }
+        }
+    }
+
+    private val activity = mock<Activity> {
+        on { componentName } doReturn COMPONENT_NAME
+        on { packageManager } doReturn mockPackageManager
+    }
+
+    @Test
+    fun getDestination_noDestination_returnNull() {
+        activityMetadata = bundleOf()
+
+        val destination = activity.getDestination()
+
+        assertThat(destination).isNull()
+    }
+
+    @Test
+    fun getDestination_withoutHighlightMenuKey() {
+        activityMetadata = bundleOf(META_DATA_KEY_DESTINATION to DESTINATION)
+
+        val (destination, highlightMenuKey) = activity.getDestination()!!
+
+        assertThat(destination).isEqualTo(DESTINATION)
+        assertThat(highlightMenuKey).isNull()
+    }
+
+    @Test
+    fun getDestination_withHighlightMenuKey() {
+        activityMetadata = bundleOf(
+            META_DATA_KEY_DESTINATION to DESTINATION,
+            META_DATA_KEY_HIGHLIGHT_MENU_KEY to HIGHLIGHT_MENU_KEY,
+        )
+
+        val (destination, highlightMenuKey) = activity.getDestination()!!
+
+        assertThat(destination).isEqualTo(DESTINATION)
+        assertThat(highlightMenuKey).isEqualTo(HIGHLIGHT_MENU_KEY)
+    }
+
+    private companion object {
+        const val PACKAGE_NAME = "package.name"
+        const val ACTIVITY_NAME = "ActivityName"
+        val COMPONENT_NAME = ComponentName(PACKAGE_NAME, ACTIVITY_NAME)
+        const val DESTINATION = "Destination"
+        const val HIGHLIGHT_MENU_KEY = "apps"
+    }
+}