Merge "Migrate AppPermissionSummary to flow" into main
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 The Android Open Source Project
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -22,15 +22,15 @@ import android.content.Intent
|
|||||||
import android.content.pm.ApplicationInfo
|
import android.content.pm.ApplicationInfo
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.lifecycle.LiveData
|
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settingslib.spa.widget.preference.Preference
|
import com.android.settingslib.spa.widget.preference.Preference
|
||||||
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
||||||
|
import com.android.settingslib.spaprivileged.framework.compose.placeholder
|
||||||
import com.android.settingslib.spaprivileged.model.app.userHandle
|
import com.android.settingslib.spaprivileged.model.app.userHandle
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
private const val TAG = "AppPermissionPreference"
|
private const val TAG = "AppPermissionPreference"
|
||||||
private const val EXTRA_HIDE_INFO_BUTTON = "hideInfoButton"
|
private const val EXTRA_HIDE_INFO_BUTTON = "hideInfoButton"
|
||||||
@@ -38,14 +38,11 @@ private const val EXTRA_HIDE_INFO_BUTTON = "hideInfoButton"
|
|||||||
@Composable
|
@Composable
|
||||||
fun AppPermissionPreference(
|
fun AppPermissionPreference(
|
||||||
app: ApplicationInfo,
|
app: ApplicationInfo,
|
||||||
summaryLiveData: LiveData<AppPermissionSummaryState> = rememberAppPermissionSummary(app),
|
summaryFlow: Flow<AppPermissionSummaryState> = rememberAppPermissionSummary(app),
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val summaryState = summaryLiveData.observeAsState(
|
val summaryState = summaryFlow.collectAsStateWithLifecycle(
|
||||||
initial = AppPermissionSummaryState(
|
initialValue = AppPermissionSummaryState(summary = placeholder(), enabled = false),
|
||||||
summary = stringResource(R.string.summary_placeholder),
|
|
||||||
enabled = false,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
Preference(
|
Preference(
|
||||||
model = remember {
|
model = remember {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 The Android Open Source Project
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -18,18 +18,22 @@ package com.android.settings.spa.app.appinfo
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.ApplicationInfo
|
import android.content.pm.ApplicationInfo
|
||||||
import android.content.pm.PackageManager.OnPermissionsChangedListener
|
|
||||||
import android.icu.text.ListFormatter
|
import android.icu.text.ListFormatter
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.lifecycle.LiveData
|
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settingslib.applications.PermissionsSummaryHelper
|
import com.android.settingslib.applications.PermissionsSummaryHelper
|
||||||
import com.android.settingslib.applications.PermissionsSummaryHelper.PermissionsResultCallback
|
|
||||||
import com.android.settingslib.spa.framework.util.formatString
|
import com.android.settingslib.spa.framework.util.formatString
|
||||||
import com.android.settingslib.spaprivileged.framework.common.asUser
|
import com.android.settingslib.spaprivileged.framework.common.asUser
|
||||||
|
import com.android.settingslib.spaprivileged.model.app.permissionsChangedFlow
|
||||||
import com.android.settingslib.spaprivileged.model.app.userHandle
|
import com.android.settingslib.spaprivileged.model.app.userHandle
|
||||||
|
import kotlin.coroutines.resume
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.flowOn
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
|
|
||||||
data class AppPermissionSummaryState(
|
data class AppPermissionSummaryState(
|
||||||
val summary: String,
|
val summary: String,
|
||||||
@@ -37,58 +41,40 @@ data class AppPermissionSummaryState(
|
|||||||
)
|
)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun rememberAppPermissionSummary(app: ApplicationInfo): AppPermissionSummaryLiveData {
|
fun rememberAppPermissionSummary(app: ApplicationInfo): Flow<AppPermissionSummaryState> {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
return remember(app) { AppPermissionSummaryLiveData(context, app) }
|
return remember(app) { AppPermissionSummaryRepository(context, app).flow }
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppPermissionSummaryLiveData(
|
class AppPermissionSummaryRepository(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val app: ApplicationInfo,
|
private val app: ApplicationInfo,
|
||||||
) : LiveData<AppPermissionSummaryState>() {
|
) {
|
||||||
private val userContext = context.asUser(app.userHandle)
|
private val userContext = context.asUser(app.userHandle)
|
||||||
private val userPackageManager = userContext.packageManager
|
|
||||||
|
|
||||||
private val onPermissionsChangedListener = OnPermissionsChangedListener { uid ->
|
val flow = context.permissionsChangedFlow(app)
|
||||||
if (uid == app.uid) update()
|
.map { getPermissionSummary() }
|
||||||
}
|
.flowOn(Dispatchers.Default)
|
||||||
|
|
||||||
override fun onActive() {
|
private suspend fun getPermissionSummary() = suspendCancellableCoroutine { continuation ->
|
||||||
userPackageManager.addOnPermissionsChangeListener(onPermissionsChangedListener)
|
|
||||||
if (app.isArchived) {
|
|
||||||
postValue(noPermissionRequestedState())
|
|
||||||
} else {
|
|
||||||
update()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onInactive() {
|
|
||||||
userPackageManager.removeOnPermissionsChangeListener(onPermissionsChangedListener)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun update() {
|
|
||||||
PermissionsSummaryHelper.getPermissionSummary(
|
PermissionsSummaryHelper.getPermissionSummary(
|
||||||
userContext, app.packageName, permissionsCallback
|
userContext,
|
||||||
)
|
app.packageName,
|
||||||
}
|
) { requestedPermissionCount: Int,
|
||||||
|
|
||||||
private val permissionsCallback = object : PermissionsResultCallback {
|
|
||||||
override fun onPermissionSummaryResult(
|
|
||||||
requestedPermissionCount: Int,
|
|
||||||
additionalGrantedPermissionCount: Int,
|
additionalGrantedPermissionCount: Int,
|
||||||
grantedGroupLabels: List<CharSequence>,
|
grantedGroupLabels: List<CharSequence> ->
|
||||||
) {
|
val summaryState = if (requestedPermissionCount == 0) {
|
||||||
if (requestedPermissionCount == 0) {
|
noPermissionRequestedState()
|
||||||
postValue(noPermissionRequestedState())
|
} else {
|
||||||
return
|
|
||||||
}
|
|
||||||
val labels = getDisplayLabels(additionalGrantedPermissionCount, grantedGroupLabels)
|
val labels = getDisplayLabels(additionalGrantedPermissionCount, grantedGroupLabels)
|
||||||
val summary = if (labels.isNotEmpty()) {
|
val summary = if (labels.isNotEmpty()) {
|
||||||
ListFormatter.getInstance().format(labels)
|
ListFormatter.getInstance().format(labels)
|
||||||
} else {
|
} else {
|
||||||
context.getString(R.string.runtime_permissions_summary_no_permissions_granted)
|
context.getString(R.string.runtime_permissions_summary_no_permissions_granted)
|
||||||
}
|
}
|
||||||
postValue(AppPermissionSummaryState(summary = summary, enabled = true))
|
AppPermissionSummaryState(summary = summary, enabled = true)
|
||||||
|
}
|
||||||
|
continuation.resume(summaryState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,9 +86,9 @@ class AppPermissionSummaryLiveData(
|
|||||||
private fun getDisplayLabels(
|
private fun getDisplayLabels(
|
||||||
additionalGrantedPermissionCount: Int,
|
additionalGrantedPermissionCount: Int,
|
||||||
grantedGroupLabels: List<CharSequence>,
|
grantedGroupLabels: List<CharSequence>,
|
||||||
): List<CharSequence> = when (additionalGrantedPermissionCount) {
|
): List<CharSequence> = if (additionalGrantedPermissionCount == 0) {
|
||||||
0 -> grantedGroupLabels
|
grantedGroupLabels
|
||||||
else -> {
|
} else {
|
||||||
grantedGroupLabels +
|
grantedGroupLabels +
|
||||||
// N additional permissions.
|
// N additional permissions.
|
||||||
context.formatString(
|
context.formatString(
|
||||||
@@ -110,5 +96,4 @@ class AppPermissionSummaryLiveData(
|
|||||||
"count" to additionalGrantedPermissionCount,
|
"count" to additionalGrantedPermissionCount,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2023 The Android Open Source Project
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -26,35 +26,32 @@ import androidx.compose.ui.test.junit4.createComposeRule
|
|||||||
import androidx.compose.ui.test.onNodeWithText
|
import androidx.compose.ui.test.onNodeWithText
|
||||||
import androidx.compose.ui.test.onRoot
|
import androidx.compose.ui.test.onRoot
|
||||||
import androidx.compose.ui.test.performClick
|
import androidx.compose.ui.test.performClick
|
||||||
import androidx.lifecycle.MutableLiveData
|
|
||||||
import androidx.test.core.app.ApplicationProvider
|
import androidx.test.core.app.ApplicationProvider
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settingslib.spa.testutils.delay
|
import com.android.settingslib.spa.testutils.delay
|
||||||
import com.android.settingslib.spaprivileged.model.app.userHandle
|
import com.android.settingslib.spaprivileged.model.app.userHandle
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.mockito.ArgumentCaptor
|
import org.mockito.kotlin.any
|
||||||
import org.mockito.Mockito.any
|
import org.mockito.kotlin.argumentCaptor
|
||||||
import org.mockito.Mockito.doNothing
|
import org.mockito.kotlin.doNothing
|
||||||
import org.mockito.Mockito.eq
|
import org.mockito.kotlin.eq
|
||||||
import org.mockito.Mockito.verify
|
import org.mockito.kotlin.spy
|
||||||
import org.mockito.Spy
|
import org.mockito.kotlin.verify
|
||||||
import org.mockito.junit.MockitoJUnit
|
import org.mockito.kotlin.whenever
|
||||||
import org.mockito.junit.MockitoRule
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class AppPermissionPreferenceTest {
|
class AppPermissionPreferenceTest {
|
||||||
@get:Rule
|
@get:Rule
|
||||||
val composeTestRule = createComposeRule()
|
val composeTestRule = createComposeRule()
|
||||||
|
|
||||||
@get:Rule
|
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
|
||||||
val mockito: MockitoRule = MockitoJUnit.rule()
|
doNothing().whenever(mock).startActivityAsUser(any(), any())
|
||||||
|
}
|
||||||
@Spy
|
|
||||||
private val context: Context = ApplicationProvider.getApplicationContext()
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun title_display() {
|
fun title_display() {
|
||||||
@@ -66,15 +63,13 @@ class AppPermissionPreferenceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun whenClick_startActivity() {
|
fun whenClick_startActivity() {
|
||||||
doNothing().`when`(context).startActivityAsUser(any(), any())
|
|
||||||
|
|
||||||
setContent()
|
setContent()
|
||||||
composeTestRule.onRoot().performClick()
|
composeTestRule.onRoot().performClick()
|
||||||
composeTestRule.delay()
|
composeTestRule.delay()
|
||||||
|
|
||||||
val intentCaptor = ArgumentCaptor.forClass(Intent::class.java)
|
val intent = argumentCaptor {
|
||||||
verify(context).startActivityAsUser(intentCaptor.capture(), eq(APP.userHandle))
|
verify(context).startActivityAsUser(capture(), eq(APP.userHandle))
|
||||||
val intent = intentCaptor.value
|
}.firstValue
|
||||||
assertThat(intent.action).isEqualTo(Intent.ACTION_MANAGE_APP_PERMISSIONS)
|
assertThat(intent.action).isEqualTo(Intent.ACTION_MANAGE_APP_PERMISSIONS)
|
||||||
assertThat(intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME)).isEqualTo(PACKAGE_NAME)
|
assertThat(intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME)).isEqualTo(PACKAGE_NAME)
|
||||||
assertThat(intent.getBooleanExtra(EXTRA_HIDE_INFO_BUTTON, false)).isEqualTo(true)
|
assertThat(intent.getBooleanExtra(EXTRA_HIDE_INFO_BUTTON, false)).isEqualTo(true)
|
||||||
@@ -85,7 +80,7 @@ class AppPermissionPreferenceTest {
|
|||||||
CompositionLocalProvider(LocalContext provides context) {
|
CompositionLocalProvider(LocalContext provides context) {
|
||||||
AppPermissionPreference(
|
AppPermissionPreference(
|
||||||
app = APP,
|
app = APP,
|
||||||
summaryLiveData = MutableLiveData(
|
summaryFlow = flowOf(
|
||||||
AppPermissionSummaryState(summary = SUMMARY, enabled = true)
|
AppPermissionSummaryState(summary = SUMMARY, enabled = true)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 The Android Open Source Project
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -19,7 +19,6 @@ package com.android.settings.spa.app.appinfo
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.ApplicationInfo
|
import android.content.pm.ApplicationInfo
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
|
||||||
import androidx.test.core.app.ApplicationProvider
|
import androidx.test.core.app.ApplicationProvider
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
|
import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
|
||||||
@@ -27,50 +26,42 @@ import com.android.settings.R
|
|||||||
import com.android.settings.testutils.mockAsUser
|
import com.android.settings.testutils.mockAsUser
|
||||||
import com.android.settingslib.applications.PermissionsSummaryHelper
|
import com.android.settingslib.applications.PermissionsSummaryHelper
|
||||||
import com.android.settingslib.applications.PermissionsSummaryHelper.PermissionsResultCallback
|
import com.android.settingslib.applications.PermissionsSummaryHelper.PermissionsResultCallback
|
||||||
import com.android.settingslib.spa.testutils.getOrAwaitValue
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.mockito.Mock
|
|
||||||
import org.mockito.Mockito.any
|
|
||||||
import org.mockito.Mockito.doReturn
|
|
||||||
import org.mockito.Mockito.eq
|
|
||||||
import org.mockito.Mockito.never
|
|
||||||
import org.mockito.Mockito.verify
|
|
||||||
import org.mockito.MockitoSession
|
import org.mockito.MockitoSession
|
||||||
import org.mockito.Spy
|
import org.mockito.kotlin.any
|
||||||
|
import org.mockito.kotlin.doReturn
|
||||||
|
import org.mockito.kotlin.eq
|
||||||
|
import org.mockito.kotlin.mock
|
||||||
|
import org.mockito.kotlin.spy
|
||||||
|
import org.mockito.kotlin.whenever
|
||||||
import org.mockito.quality.Strictness
|
import org.mockito.quality.Strictness
|
||||||
import org.mockito.Mockito.`when` as whenever
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class AppPermissionSummaryTest {
|
class AppPermissionSummaryTest {
|
||||||
@get:Rule
|
|
||||||
val instantTaskExecutorRule = InstantTaskExecutorRule()
|
|
||||||
|
|
||||||
private lateinit var mockSession: MockitoSession
|
private lateinit var mockSession: MockitoSession
|
||||||
|
|
||||||
@Spy
|
private val mockPackageManager = mock<PackageManager>()
|
||||||
private var context: Context = ApplicationProvider.getApplicationContext()
|
|
||||||
|
|
||||||
@Mock
|
private var context: Context = spy(ApplicationProvider.getApplicationContext()) {
|
||||||
private lateinit var packageManager: PackageManager
|
mock.mockAsUser()
|
||||||
|
on { packageManager } doReturn mockPackageManager
|
||||||
|
}
|
||||||
|
|
||||||
private lateinit var summaryLiveData: AppPermissionSummaryLiveData
|
private val summaryRepository = AppPermissionSummaryRepository(context, APP)
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
mockSession = mockitoSession()
|
mockSession = mockitoSession()
|
||||||
.initMocks(this)
|
|
||||||
.mockStatic(PermissionsSummaryHelper::class.java)
|
.mockStatic(PermissionsSummaryHelper::class.java)
|
||||||
.strictness(Strictness.LENIENT)
|
.strictness(Strictness.LENIENT)
|
||||||
.startMocking()
|
.startMocking()
|
||||||
context.mockAsUser()
|
|
||||||
whenever(context.packageManager).thenReturn(packageManager)
|
|
||||||
|
|
||||||
summaryLiveData = AppPermissionSummaryLiveData(context, APP)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun mockGetPermissionSummary(
|
private fun mockGetPermissionSummary(
|
||||||
@@ -95,22 +86,10 @@ class AppPermissionSummaryTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun permissionsChangeListener() {
|
fun summary_noPermissionsRequested() = runBlocking {
|
||||||
mockGetPermissionSummary()
|
|
||||||
|
|
||||||
summaryLiveData.getOrAwaitValue {
|
|
||||||
verify(packageManager).addOnPermissionsChangeListener(any())
|
|
||||||
verify(packageManager, never()).removeOnPermissionsChangeListener(any())
|
|
||||||
}
|
|
||||||
|
|
||||||
verify(packageManager).removeOnPermissionsChangeListener(any())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun summary_noPermissionsRequested() {
|
|
||||||
mockGetPermissionSummary(requestedPermissionCount = 0)
|
mockGetPermissionSummary(requestedPermissionCount = 0)
|
||||||
|
|
||||||
val (summary, enabled) = summaryLiveData.getOrAwaitValue()!!
|
val (summary, enabled) = summaryRepository.flow.first()
|
||||||
|
|
||||||
assertThat(summary).isEqualTo(
|
assertThat(summary).isEqualTo(
|
||||||
context.getString(R.string.runtime_permissions_summary_no_permissions_requested)
|
context.getString(R.string.runtime_permissions_summary_no_permissions_requested)
|
||||||
@@ -119,10 +98,10 @@ class AppPermissionSummaryTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun summary_noPermissionsGranted() {
|
fun summary_noPermissionsGranted() = runBlocking {
|
||||||
mockGetPermissionSummary(requestedPermissionCount = 1, grantedGroupLabels = emptyList())
|
mockGetPermissionSummary(requestedPermissionCount = 1, grantedGroupLabels = emptyList())
|
||||||
|
|
||||||
val (summary, enabled) = summaryLiveData.getOrAwaitValue()!!
|
val (summary, enabled) = summaryRepository.flow.first()
|
||||||
|
|
||||||
assertThat(summary).isEqualTo(
|
assertThat(summary).isEqualTo(
|
||||||
context.getString(R.string.runtime_permissions_summary_no_permissions_granted)
|
context.getString(R.string.runtime_permissions_summary_no_permissions_granted)
|
||||||
@@ -131,34 +110,34 @@ class AppPermissionSummaryTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun onPermissionSummaryResult_hasRuntimePermission_shouldSetPermissionAsSummary() {
|
fun summary_hasRuntimePermission_usePermissionAsSummary() = runBlocking {
|
||||||
mockGetPermissionSummary(
|
mockGetPermissionSummary(
|
||||||
requestedPermissionCount = 1,
|
requestedPermissionCount = 1,
|
||||||
grantedGroupLabels = listOf(PERMISSION),
|
grantedGroupLabels = listOf(PERMISSION),
|
||||||
)
|
)
|
||||||
|
|
||||||
val (summary, enabled) = summaryLiveData.getOrAwaitValue()!!
|
val (summary, enabled) = summaryRepository.flow.first()
|
||||||
|
|
||||||
assertThat(summary).isEqualTo(PERMISSION)
|
assertThat(summary).isEqualTo(PERMISSION)
|
||||||
assertThat(enabled).isTrue()
|
assertThat(enabled).isTrue()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun onPermissionSummaryResult_hasAdditionalPermission_shouldSetAdditionalSummary() {
|
fun summary_hasAdditionalPermission_containsAdditionalSummary() = runBlocking {
|
||||||
mockGetPermissionSummary(
|
mockGetPermissionSummary(
|
||||||
requestedPermissionCount = 5,
|
requestedPermissionCount = 5,
|
||||||
additionalGrantedPermissionCount = 2,
|
additionalGrantedPermissionCount = 2,
|
||||||
grantedGroupLabels = listOf(PERMISSION),
|
grantedGroupLabels = listOf(PERMISSION),
|
||||||
)
|
)
|
||||||
|
|
||||||
val (summary, enabled) = summaryLiveData.getOrAwaitValue()!!
|
val (summary, enabled) = summaryRepository.flow.first()
|
||||||
|
|
||||||
assertThat(summary).isEqualTo("Storage and 2 additional permissions")
|
assertThat(summary).isEqualTo("Storage and 2 additional permissions")
|
||||||
assertThat(enabled).isTrue()
|
assertThat(enabled).isTrue()
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
const val PACKAGE_NAME = "packageName"
|
const val PACKAGE_NAME = "package.name"
|
||||||
const val PERMISSION = "Storage"
|
const val PERMISSION = "Storage"
|
||||||
val APP = ApplicationInfo().apply {
|
val APP = ApplicationInfo().apply {
|
||||||
packageName = PACKAGE_NAME
|
packageName = PACKAGE_NAME
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 The Android Open Source Project
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -17,10 +17,11 @@
|
|||||||
package com.android.settings.testutils
|
package com.android.settings.testutils
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import org.mockito.Mockito.any
|
import org.mockito.kotlin.any
|
||||||
import org.mockito.Mockito.doReturn
|
import org.mockito.kotlin.doReturn
|
||||||
import org.mockito.Mockito.eq
|
import org.mockito.kotlin.eq
|
||||||
|
import org.mockito.kotlin.whenever
|
||||||
|
|
||||||
fun Context.mockAsUser() {
|
fun Context.mockAsUser() {
|
||||||
doReturn(this).`when`(this).createContextAsUser(any(), eq(0))
|
doReturn(this).whenever(this).createContextAsUser(any(), eq(0))
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user