diff --git a/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt b/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt index 2ff0bfe716b..cb74388278e 100644 --- a/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt +++ b/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt @@ -16,7 +16,6 @@ package com.android.settings.spa.app.appinfo -import android.app.ActivityManager import android.app.settings.SettingsEnums import android.content.Context import android.content.Intent @@ -29,8 +28,10 @@ import android.util.Log import androidx.compose.runtime.Composable import com.android.settings.overlay.FeatureFactory import com.android.settingslib.spa.framework.compose.LocalNavController +import com.android.settingslib.spaprivileged.framework.common.activityManager import com.android.settingslib.spaprivileged.framework.common.asUser import com.android.settingslib.spaprivileged.framework.compose.DisposableBroadcastReceiverAsUser +import com.android.settingslib.spaprivileged.model.app.IPackageManagers import com.android.settingslib.spaprivileged.model.app.PackageManagers import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -48,6 +49,7 @@ class PackageInfoPresenter( val packageName: String, val userId: Int, private val coroutineScope: CoroutineScope, + private val packageManagers: IPackageManagers = PackageManagers, ) { private val metricsFeatureProvider = FeatureFactory.getFactory(context).metricsFeatureProvider private val userHandle = UserHandle.of(userId) @@ -134,9 +136,8 @@ class PackageInfoPresenter( fun forceStop() { logAction(SettingsEnums.ACTION_APP_FORCE_STOP) coroutineScope.launch(Dispatchers.Default) { - val activityManager = context.getSystemService(ActivityManager::class.java)!! Log.d(TAG, "Stopping package $packageName") - activityManager.forceStopPackageAsUser(packageName, userId) + context.activityManager.forceStopPackageAsUser(packageName, userId) notifyChange() } } @@ -146,7 +147,7 @@ class PackageInfoPresenter( } private fun getPackageInfo() = - PackageManagers.getPackageInfoAsUser( + packageManagers.getPackageInfoAsUser( packageName = packageName, flags = PackageManager.MATCH_DISABLED_COMPONENTS or PackageManager.GET_PERMISSIONS, userId = userId, diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppAllServicesPreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppAllServicesPreferenceTest.kt index 41f57af9554..291c9d18082 100644 --- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppAllServicesPreferenceTest.kt +++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppAllServicesPreferenceTest.kt @@ -63,8 +63,7 @@ import org.mockito.Mockito.`when` as whenever @RunWith(AndroidJUnit4::class) class AppAllServicesPreferenceTest { - @JvmField - @Rule + @get:Rule val mockito: MockitoRule = MockitoJUnit.rule() @get:Rule diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppButtonRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppButtonRepositoryTest.kt index 4e1b1b63ab2..49b60fba6bb 100644 --- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppButtonRepositoryTest.kt +++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppButtonRepositoryTest.kt @@ -40,8 +40,7 @@ import org.mockito.Mockito.`when` as whenever @RunWith(AndroidJUnit4::class) class AppButtonRepositoryTest { - @JvmField - @Rule + @get:Rule val mockito: MockitoRule = MockitoJUnit.rule() @Spy diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppOpenByDefaultPreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppOpenByDefaultPreferenceTest.kt index a402a022392..05a6753c9ba 100644 --- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppOpenByDefaultPreferenceTest.kt +++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppOpenByDefaultPreferenceTest.kt @@ -35,6 +35,7 @@ import androidx.compose.ui.test.onRoot import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settings.R +import com.android.settings.testutils.mockAsUser import com.android.settingslib.spaprivileged.framework.common.domainVerificationManager import org.junit.Before import org.junit.Rule @@ -51,8 +52,7 @@ import org.mockito.Mockito.`when` as whenever @RunWith(AndroidJUnit4::class) class AppOpenByDefaultPreferenceTest { - @JvmField - @Rule + @get:Rule val mockito: MockitoRule = MockitoJUnit.rule() @get:Rule @@ -76,7 +76,7 @@ class AppOpenByDefaultPreferenceTest { @Before fun setUp() { whenever(context.packageManager).thenReturn(packageManager) - doReturn(context).`when`(context).createContextAsUser(any(), anyInt()) + context.mockAsUser() whenever(context.domainVerificationManager).thenReturn(domainVerificationManager) whenever(allowedUserState.isLinkHandlingAllowed).thenReturn(true) whenever(notAllowedUserState.isLinkHandlingAllowed).thenReturn(false) diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppSettingsPreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppSettingsPreferenceTest.kt index 7c6dfcefb48..d39555ab1fa 100644 --- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppSettingsPreferenceTest.kt +++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppSettingsPreferenceTest.kt @@ -56,8 +56,7 @@ import org.mockito.Mockito.`when` as whenever @RunWith(AndroidJUnit4::class) class AppSettingsPreferenceTest { - @JvmField - @Rule + @get:Rule val mockito: MockitoRule = MockitoJUnit.rule() @get:Rule diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppStoragePreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppStoragePreferenceTest.kt index 47f553bd262..397493865a7 100644 --- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppStoragePreferenceTest.kt +++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppStoragePreferenceTest.kt @@ -46,8 +46,7 @@ import org.mockito.Mockito.`when` as whenever @RunWith(AndroidJUnit4::class) class AppStoragePreferenceTest { - @JvmField - @Rule + @get:Rule val mockito: MockitoRule = MockitoJUnit.rule() @get:Rule diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppTimeSpentPreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppTimeSpentPreferenceTest.kt index b2ff4f2e8a8..6cc3e3c57e7 100644 --- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppTimeSpentPreferenceTest.kt +++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppTimeSpentPreferenceTest.kt @@ -49,8 +49,7 @@ import org.mockito.Mockito.`when` as whenever @RunWith(AndroidJUnit4::class) class AppTimeSpentPreferenceTest { - @JvmField - @Rule + @get:Rule val mockito: MockitoRule = MockitoJUnit.rule() @get:Rule diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/DefaultAppShortcutPreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/DefaultAppShortcutPreferenceTest.kt index d5f72414d0d..5c24559caee 100644 --- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/DefaultAppShortcutPreferenceTest.kt +++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/DefaultAppShortcutPreferenceTest.kt @@ -55,8 +55,7 @@ import org.mockito.Mockito.`when` as whenever @RunWith(AndroidJUnit4::class) class DefaultAppShortcutPreferenceTest { - @JvmField - @Rule + @get:Rule val mockito: MockitoRule = MockitoJUnit.rule() @get:Rule diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreferenceTest.kt index 688ef86aefc..6acdcf5a648 100644 --- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreferenceTest.kt +++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreferenceTest.kt @@ -49,6 +49,7 @@ import com.android.settings.R import com.android.settings.Utils.PROPERTY_APP_HIBERNATION_ENABLED import com.android.settings.Utils.PROPERTY_HIBERNATION_TARGETS_PRE_S_APPS import com.android.settings.testutils.TestDeviceConfig +import com.android.settings.testutils.mockAsUser import com.android.settingslib.spaprivileged.framework.common.appHibernationManager import com.android.settingslib.spaprivileged.framework.common.appOpsManager import com.android.settingslib.spaprivileged.framework.common.permissionControllerManager @@ -75,8 +76,7 @@ import org.mockito.Mockito.`when` as whenever @RunWith(AndroidJUnit4::class) class HibernationSwitchPreferenceTest { - @JvmField - @Rule + @get:Rule val mockito: MockitoRule = MockitoJUnit.rule() @get:Rule @@ -104,8 +104,7 @@ class HibernationSwitchPreferenceTest { fun setUp() { hibernationEnabledConfig.override(true) hibernationTargetsPreSConfig.override(false) - doReturn(context) - .`when`(context).createContextAsUser(UserHandle.getUserHandleForUid(UID), 0) + context.mockAsUser() whenever(context.permissionControllerManager).thenReturn(permissionControllerManager) whenever(context.appOpsManager).thenReturn(appOpsManager) whenever(context.appHibernationManager).thenReturn(appHibernationManager) diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/PackageInfoPresenterTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/PackageInfoPresenterTest.kt new file mode 100644 index 00000000000..3bfa90e2d9e --- /dev/null +++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/PackageInfoPresenterTest.kt @@ -0,0 +1,168 @@ +/* + * 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.app.appinfo + +import android.app.ActivityManager +import android.app.settings.SettingsEnums +import android.content.Context +import android.content.Intent +import android.content.pm.PackageManager +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settings.testutils.FakeFeatureFactory +import com.android.settings.testutils.mockAsUser +import com.android.settingslib.spaprivileged.framework.common.activityManager +import com.android.settingslib.spaprivileged.model.app.IPackageManagers +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.test.runTest +import org.junit.Before +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.any +import org.mockito.Mockito.doNothing +import org.mockito.Mockito.verify +import org.mockito.Spy +import org.mockito.junit.MockitoJUnit +import org.mockito.junit.MockitoRule +import org.mockito.Mockito.`when` as whenever + +@OptIn(ExperimentalCoroutinesApi::class) +@RunWith(AndroidJUnit4::class) +class PackageInfoPresenterTest { + @get:Rule + val mockito: MockitoRule = MockitoJUnit.rule() + + @Spy + private val context: Context = ApplicationProvider.getApplicationContext() + + @Mock + private lateinit var packageManager: PackageManager + + @Mock + private lateinit var activityManager: ActivityManager + + @Mock + private lateinit var packageManagers: IPackageManagers + + private val fakeFeatureFactory = FakeFeatureFactory() + private val metricsFeatureProvider = fakeFeatureFactory.metricsFeatureProvider + + @Before + fun setUp() { + context.mockAsUser() + whenever(context.packageManager).thenReturn(packageManager) + whenever(context.activityManager).thenReturn(activityManager) + } + + @Test + fun enable() = runTest { + coroutineScope { + val packageInfoPresenter = + PackageInfoPresenter(context, PACKAGE_NAME, USER_ID, this, packageManagers) + + packageInfoPresenter.enable() + } + + verifyAction(SettingsEnums.ACTION_SETTINGS_ENABLE_APP) + verify(packageManager).setApplicationEnabledSetting( + PACKAGE_NAME, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0 + ) + } + + @Test + fun disable() = runTest { + coroutineScope { + val packageInfoPresenter = + PackageInfoPresenter(context, PACKAGE_NAME, USER_ID, this, packageManagers) + + packageInfoPresenter.disable() + } + + verifyAction(SettingsEnums.ACTION_SETTINGS_DISABLE_APP) + verify(packageManager).setApplicationEnabledSetting( + PACKAGE_NAME, PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER, 0 + ) + } + + @Test + fun startUninstallActivity() = runTest { + doNothing().`when`(context).startActivityAsUser(any(), any()) + val packageInfoPresenter = + PackageInfoPresenter(context, PACKAGE_NAME, USER_ID, this, packageManagers) + + packageInfoPresenter.startUninstallActivity() + + verifyAction(SettingsEnums.ACTION_SETTINGS_UNINSTALL_APP) + val intentCaptor = ArgumentCaptor.forClass(Intent::class.java) + verify(context).startActivityAsUser(intentCaptor.capture(), any()) + with(intentCaptor.value) { + assertThat(action).isEqualTo(Intent.ACTION_UNINSTALL_PACKAGE) + assertThat(data?.schemeSpecificPart).isEqualTo(PACKAGE_NAME) + assertThat(getBooleanExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, true)).isEqualTo(false) + } + } + + @Test + fun clearInstantApp() = runTest { + coroutineScope { + val packageInfoPresenter = + PackageInfoPresenter(context, PACKAGE_NAME, USER_ID, this, packageManagers) + + packageInfoPresenter.clearInstantApp() + } + + verifyAction(SettingsEnums.ACTION_SETTINGS_CLEAR_INSTANT_APP) + verify(packageManager).deletePackageAsUser(PACKAGE_NAME, null, 0, USER_ID) + } + + @Test + fun forceStop() = runTest { + coroutineScope { + val packageInfoPresenter = + PackageInfoPresenter(context, PACKAGE_NAME, USER_ID, this, packageManagers) + + packageInfoPresenter.forceStop() + } + + verifyAction(SettingsEnums.ACTION_APP_FORCE_STOP) + verify(activityManager).forceStopPackageAsUser(PACKAGE_NAME, USER_ID) + } + + @Test + fun logAction() = runTest { + val packageInfoPresenter = + PackageInfoPresenter(context, PACKAGE_NAME, USER_ID, this, packageManagers) + + packageInfoPresenter.logAction(123) + + verifyAction(123) + } + + private fun verifyAction(category: Int) { + verify(metricsFeatureProvider).action(context, category, PACKAGE_NAME) + } + + private companion object { + const val PACKAGE_NAME = "package.name" + const val USER_ID = 0 + } +} diff --git a/tests/spa_unit/src/com/android/settings/testutils/ContextTestUtil.kt b/tests/spa_unit/src/com/android/settings/testutils/ContextTestUtil.kt new file mode 100644 index 00000000000..43b7a206efb --- /dev/null +++ b/tests/spa_unit/src/com/android/settings/testutils/ContextTestUtil.kt @@ -0,0 +1,26 @@ +/* + * 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.testutils + +import android.content.Context +import org.mockito.Mockito.any +import org.mockito.Mockito.doReturn +import org.mockito.Mockito.eq + +fun Context.mockAsUser() { + doReturn(this).`when`(this).createContextAsUser(any(), eq(0)) +}