Merge "Let SpaBridgeActivity support HIGHLIGHT_MENU_KEY" into main

This commit is contained in:
Chaohui Wang
2023-12-05 06:23:57 +00:00
committed by Android (Google) Code Review
5 changed files with 109 additions and 33 deletions

View File

@@ -1741,6 +1741,8 @@
android:targetActivity=".spa.SpaBridgeActivity"> android:targetActivity=".spa.SpaBridgeActivity">
<meta-data android:name="com.android.settings.spa.DESTINATION" <meta-data android:name="com.android.settings.spa.DESTINATION"
android:value="TogglePermissionAppList/UseFullScreenIntent"/> android:value="TogglePermissionAppList/UseFullScreenIntent"/>
<meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
android:value="@string/menu_key_apps"/>
</activity-alias> </activity-alias>
<activity-alias android:name="AppManageFullScreenIntent" <activity-alias android:name="AppManageFullScreenIntent"
@@ -1753,6 +1755,8 @@
</intent-filter> </intent-filter>
<meta-data android:name="com.android.settings.spa.DESTINATION" <meta-data android:name="com.android.settings.spa.DESTINATION"
android:value="TogglePermissionAppInfoPage/UseFullScreenIntent"/> android:value="TogglePermissionAppInfoPage/UseFullScreenIntent"/>
<meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
android:value="@string/menu_key_apps"/>
</activity-alias> </activity-alias>
<activity android:name=".applications.InstalledAppOpenByDefaultActivity" <activity android:name=".applications.InstalledAppOpenByDefaultActivity"
@@ -4967,6 +4971,8 @@
</intent-filter> </intent-filter>
<meta-data android:name="com.android.settings.spa.DESTINATION" <meta-data android:name="com.android.settings.spa.DESTINATION"
android:value="UsageStats"/> android:value="UsageStats"/>
<meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
android:value="@string/menu_key_apps"/>
</activity-alias> </activity-alias>
<!-- [b/197780098] Disable eager initialization of Jetpack libraries. --> <!-- [b/197780098] Disable eager initialization of Jetpack libraries. -->

View File

@@ -20,7 +20,6 @@ import android.app.Activity
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.os.UserHandle import android.os.UserHandle
import com.android.settings.spa.SpaBridgeActivity.Companion.getDestination
import com.android.settings.spa.SpaBridgeActivity.Companion.startSpaActivityFromBridge import com.android.settings.spa.SpaBridgeActivity.Companion.startSpaActivityFromBridge
/** /**
@@ -33,11 +32,7 @@ import com.android.settings.spa.SpaBridgeActivity.Companion.startSpaActivityFrom
class SpaAppBridgeActivity : Activity() { class SpaAppBridgeActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
getDestination()?.let { destinationPrefix -> startSpaActivityFromBridge { getDestinationForApp(it, intent) }
getDestinationForApp(destinationPrefix, intent)?.let { destination ->
startSpaActivityFromBridge(destination)
}
}
finish() finish()
} }

View File

@@ -18,12 +18,10 @@ package com.android.settings.spa
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.PackageManager.ComponentInfoFlags
import android.os.Bundle import android.os.Bundle
import androidx.annotation.VisibleForTesting
import com.android.settings.activityembedding.ActivityEmbeddingUtils import com.android.settings.activityembedding.ActivityEmbeddingUtils
import com.android.settings.activityembedding.EmbeddedDeepLinkUtils.tryStartMultiPaneDeepLink 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.SESSION_EXTERNAL
import com.android.settingslib.spa.framework.util.appendSpaParams import com.android.settingslib.spa.framework.util.appendSpaParams
@@ -37,29 +35,23 @@ import com.android.settingslib.spa.framework.util.appendSpaParams
class SpaBridgeActivity : Activity() { class SpaBridgeActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
getDestination()?.let { destination -> startSpaActivityFromBridge()
startSpaActivityFromBridge(destination)
}
finish() finish()
} }
companion object { 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) val intent = Intent(this, SpaActivity::class.java)
.appendSpaParams(destination = destination) .appendSpaParams(
.appendSpaParams(sessionName = SESSION_EXTERNAL) destination = destination,
sessionName = SESSION_EXTERNAL,
)
if (!ActivityEmbeddingUtils.isEmbeddingActivityEnabled(this) || if (!ActivityEmbeddingUtils.isEmbeddingActivityEnabled(this) ||
!tryStartMultiPaneDeepLink(intent)) { !tryStartMultiPaneDeepLink(intent, highlightMenuKey)
) {
startActivity(intent) 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"
} }
} }

View File

@@ -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"
}
}

View File

@@ -20,26 +20,34 @@ import android.app.Activity
import android.content.ComponentName import android.content.ComponentName
import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.pm.PackageManager.ComponentInfoFlags import android.os.Bundle
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.spa.SpaBridgeActivity.Companion.META_DATA_KEY_DESTINATION import com.android.settings.SettingsActivity.META_DATA_KEY_HIGHLIGHT_MENU_KEY
import com.android.settings.spa.SpaBridgeActivity.Companion.getDestination 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 com.google.common.truth.Truth.assertThat
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.kotlin.any import org.mockito.kotlin.any
import org.mockito.kotlin.doAnswer
import org.mockito.kotlin.doReturn import org.mockito.kotlin.doReturn
import org.mockito.kotlin.eq import org.mockito.kotlin.eq
import org.mockito.kotlin.mock import org.mockito.kotlin.mock
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
class SpaBridgeActivityTest { class SpaDestinationTest {
private var activityMetadata: Bundle = bundleOf()
private val mockPackageManager = mock<PackageManager> { private val mockPackageManager = mock<PackageManager> {
on { getActivityInfo(eq(COMPONENT_NAME), any<ComponentInfoFlags>()) } doReturn on {
ActivityInfo().apply { getActivityInfo(
metaData = bundleOf(META_DATA_KEY_DESTINATION to DESTINATION) eq(COMPONENT_NAME),
} any<PackageManager.ComponentInfoFlags>()
)
} doAnswer {
ActivityInfo().apply { metaData = activityMetadata }
}
} }
private val activity = mock<Activity> { private val activity = mock<Activity> {
@@ -48,10 +56,35 @@ class SpaBridgeActivityTest {
} }
@Test @Test
fun getDestination() { fun getDestination_noDestination_returnNull() {
activityMetadata = bundleOf()
val destination = activity.getDestination() 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(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 { private companion object {
@@ -59,5 +92,6 @@ class SpaBridgeActivityTest {
const val ACTIVITY_NAME = "ActivityName" const val ACTIVITY_NAME = "ActivityName"
val COMPONENT_NAME = ComponentName(PACKAGE_NAME, ACTIVITY_NAME) val COMPONENT_NAME = ComponentName(PACKAGE_NAME, ACTIVITY_NAME)
const val DESTINATION = "Destination" const val DESTINATION = "Destination"
const val HIGHLIGHT_MENU_KEY = "apps"
} }
} }