From a9c624b0d31e46ee14af48b8571a084dc2c4a296 Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Fri, 23 Dec 2022 16:48:40 +0800 Subject: [PATCH] Add SpaAppBridgeActivity for application usage This requires the user to pass into the package name, which enabling the feature of navigating to app info pages. Bug: 263553430 Test: Manually with Settings Change-Id: I9405e3732d99f78cd87e62d73b0c9519a8e2d71f --- AndroidManifest.xml | 1 + src/com/android/settings/spa/SpaActivity.kt | 17 +++- .../settings/spa/SpaAppBridgeActivity.kt | 39 ++++++++++ .../android/settings/spa/SpaBridgeActivity.kt | 12 +-- .../android/settings/spa/SpaActivityTest.kt | 78 +++++++++++++++++++ 5 files changed, 138 insertions(+), 9 deletions(-) create mode 100644 src/com/android/settings/spa/SpaAppBridgeActivity.kt mode change 100755 => 100644 src/com/android/settings/spa/SpaBridgeActivity.kt create mode 100644 tests/spa_unit/src/com/android/settings/spa/SpaActivityTest.kt diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 36e4a9802d4..8739782e171 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -4744,6 +4744,7 @@ android:configChanges="orientation|screenLayout|screenSize|smallestScreenSize" android:exported="false" /> + , otherwise all its pages will be exported. + * So need this bridge activity to sit in the middle of and [SpaActivity]. + */ +class SpaAppBridgeActivity : Activity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + getDestination()?.let { destination -> + startSpaActivityForApp(destination, intent) + } + finish() + } +} diff --git a/src/com/android/settings/spa/SpaBridgeActivity.kt b/src/com/android/settings/spa/SpaBridgeActivity.kt old mode 100755 new mode 100644 index 9e433e449ca..904be88376d --- a/src/com/android/settings/spa/SpaBridgeActivity.kt +++ b/src/com/android/settings/spa/SpaBridgeActivity.kt @@ -33,17 +33,17 @@ class SpaBridgeActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) getDestination()?.let { destination -> - startSpaActivity(this, destination) + startSpaActivity(destination) } finish() } - private fun getDestination(): String? = - packageManager.getActivityInfo( - componentName, ComponentInfoFlags.of(PackageManager.GET_META_DATA.toLong()) - ).metaData.getString(META_DATA_KEY_DESTINATION) - companion object { + fun Activity.getDestination(): String? = + packageManager.getActivityInfo( + componentName, ComponentInfoFlags.of(PackageManager.GET_META_DATA.toLong()) + ).metaData.getString(META_DATA_KEY_DESTINATION) + private const val META_DATA_KEY_DESTINATION = "com.android.settings.spa.DESTINATION" } } diff --git a/tests/spa_unit/src/com/android/settings/spa/SpaActivityTest.kt b/tests/spa_unit/src/com/android/settings/spa/SpaActivityTest.kt new file mode 100644 index 00000000000..247f3692dbb --- /dev/null +++ b/tests/spa_unit/src/com/android/settings/spa/SpaActivityTest.kt @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2022 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.content.Context +import android.content.Intent +import android.net.Uri +import android.os.UserHandle +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settings.spa.SpaActivity.Companion.startSpaActivity +import com.android.settings.spa.SpaActivity.Companion.startSpaActivityForApp +import com.android.settingslib.spa.framework.util.KEY_DESTINATION +import com.google.common.truth.Truth.assertThat +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.junit.MockitoJUnit +import org.mockito.junit.MockitoRule + +@RunWith(AndroidJUnit4::class) +class SpaActivityTest { + @get:Rule + val mockito: MockitoRule = MockitoJUnit.rule() + + @Mock + private lateinit var context: Context + + @Test + fun startSpaActivity() { + context.startSpaActivity(DESTINATION) + + val intentCaptor = ArgumentCaptor.forClass(Intent::class.java) + verify(context).startActivity(intentCaptor.capture()) + val intent = intentCaptor.value + assertThat(intent.component?.className).isEqualTo(SpaActivity::class.qualifiedName) + assertThat(intent.getStringExtra(KEY_DESTINATION)).isEqualTo(DESTINATION) + } + + @Test + fun startSpaActivityForApp() { + val intent = Intent().apply { + data = Uri.parse("package:$PACKAGE_NAME") + putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.of(USER_ID)) + } + + context.startSpaActivityForApp(DESTINATION, intent) + + val intentCaptor = ArgumentCaptor.forClass(Intent::class.java) + verify(context).startActivity(intentCaptor.capture()) + val capturedIntent = intentCaptor.value + assertThat(capturedIntent.component?.className).isEqualTo(SpaActivity::class.qualifiedName) + assertThat(capturedIntent.getStringExtra(KEY_DESTINATION)) + .isEqualTo("Destination/package.name/1") + } + + private companion object { + const val DESTINATION = "Destination" + const val PACKAGE_NAME = "package.name" + const val USER_ID = 1 + } +}