summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author mrulhania <mrulhania@google.com> 2024-09-26 05:30:44 -0700
committer Manjeet Rulhania <mrulhania@google.com> 2024-09-27 11:18:39 +0000
commit27884097f7a2c40efb6a3f385d2550bb349f2b83 (patch)
treea7e91d4cb2f3467341107169a3e33f204cef3cdb
parentbce9c37d6cc0d9f67c44e75125180ce736d4bad4 (diff)
Show attribution label from location provider only on permission timeline page
Bug: 369606734 Test: atest PermissionHistoryTest Test: atest PermissionControllerMockingTests FLAG: com.android.permission.flags.permission_timeline_attribution_label_fix Relnote: bug fix Change-Id: Ic3f9256d3fef0c19f557142f332364fbe0aadab3
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/domain/usecase/v31/GetPermissionGroupUsageDetailsUseCase.kt88
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/domain/usecase/GetPermissionGroupUsageDetailsUseCaseTest.kt206
-rw-r--r--flags/Android.bp1
-rw-r--r--flags/flags.aconfig9
4 files changed, 192 insertions, 112 deletions
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/domain/usecase/v31/GetPermissionGroupUsageDetailsUseCase.kt b/PermissionController/src/com/android/permissioncontroller/permission/domain/usecase/v31/GetPermissionGroupUsageDetailsUseCase.kt
index 16eaaf6f2..edf6e22e5 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/domain/usecase/v31/GetPermissionGroupUsageDetailsUseCase.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/domain/usecase/v31/GetPermissionGroupUsageDetailsUseCase.kt
@@ -21,6 +21,7 @@ import android.app.AppOpsManager
import android.os.UserHandle
import android.permission.flags.Flags
import com.android.modules.utils.build.SdkLevel
+import com.android.permissioncontroller.PermissionControllerApplication
import com.android.permissioncontroller.appops.data.model.v31.DiscretePackageOpsModel
import com.android.permissioncontroller.appops.data.model.v31.DiscretePackageOpsModel.DiscreteOpModel
import com.android.permissioncontroller.appops.data.repository.v31.AppOpRepository
@@ -29,6 +30,7 @@ import com.android.permissioncontroller.permission.domain.model.v31.PermissionTi
import com.android.permissioncontroller.permission.domain.model.v31.PermissionTimelineUsageModelWrapper
import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel.Companion.CLUSTER_SPACING_MINUTES
import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel.Companion.ONE_MINUTE_MS
+import com.android.permissioncontroller.permission.utils.LocationUtils
import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.android.permissioncontroller.pm.data.repository.v31.PackageRepository
import com.android.permissioncontroller.role.data.repository.v31.RoleRepository
@@ -72,7 +74,7 @@ class GetPermissionGroupUsageDetailsUseCase(
permissionGroup,
packageOps.userId,
permissionRepository,
- packageRepository
+ packageRepository,
)
packageOps
}
@@ -86,43 +88,61 @@ class GetPermissionGroupUsageDetailsUseCase(
}
}
+ // show attribution on T+ for location provider only..
+ private fun shouldShowAttributionLabel(packageName: String): Boolean {
+ return if (com.android.permission.flags.Flags.permissionTimelineAttributionLabelFix()) {
+ SdkLevel.isAtLeastT() &&
+ LocationUtils.isLocationProvider(PermissionControllerApplication.get(), packageName)
+ } else true
+ }
+
/** Group app op accesses by attribution label if it is available and user visible. */
private suspend fun List<DiscretePackageOpsModel>.groupByAttributionLabelIfNeeded() =
map { packageOps ->
- val attributionInfo =
- packageRepository.getPackageAttributionInfo(
- packageOps.packageName,
- UserHandle.of(packageOps.userId)
- )
- if (attributionInfo != null) {
- if (attributionInfo.areUserVisible && attributionInfo.tagResourceMap != null) {
- val attributionLabelOpsMap: Map<String?, List<DiscreteOpModel>> =
- packageOps.appOpAccesses
- .map { appOpEntry ->
- val resourceId =
- attributionInfo.tagResourceMap[appOpEntry.attributionTag]
- val label = attributionInfo.resourceLabelMap?.get(resourceId)
- label to appOpEntry
- }
- .groupBy { labelAppOpEntryPair -> labelAppOpEntryPair.first }
- .mapValues { (_, values) ->
- values.map { labelAppOpEntryPair -> labelAppOpEntryPair.second }
- }
+ if (!shouldShowAttributionLabel(packageOps.packageName)) {
+ listOf(packageOps)
+ } else {
+ val attributionInfo =
+ packageRepository.getPackageAttributionInfo(
+ packageOps.packageName,
+ UserHandle.of(packageOps.userId),
+ )
+ if (attributionInfo != null) {
+ if (
+ attributionInfo.areUserVisible && attributionInfo.tagResourceMap != null
+ ) {
+ val attributionLabelOpsMap: Map<String?, List<DiscreteOpModel>> =
+ packageOps.appOpAccesses
+ .map { appOpEntry ->
+ val resourceId =
+ attributionInfo.tagResourceMap[
+ appOpEntry.attributionTag]
+ val label =
+ attributionInfo.resourceLabelMap?.get(resourceId)
+ label to appOpEntry
+ }
+ .groupBy { labelAppOpEntryPair -> labelAppOpEntryPair.first }
+ .mapValues { (_, values) ->
+ values.map { labelAppOpEntryPair ->
+ labelAppOpEntryPair.second
+ }
+ }
- attributionLabelOpsMap.map { labelAppOpsEntry ->
- DiscretePackageOpsModel(
- packageOps.packageName,
- packageOps.userId,
- appOpAccesses = labelAppOpsEntry.value,
- attributionLabel = labelAppOpsEntry.key,
- isUserSensitive = packageOps.isUserSensitive,
- )
+ attributionLabelOpsMap.map { labelAppOpsEntry ->
+ DiscretePackageOpsModel(
+ packageOps.packageName,
+ packageOps.userId,
+ appOpAccesses = labelAppOpsEntry.value,
+ attributionLabel = labelAppOpsEntry.key,
+ isUserSensitive = packageOps.isUserSensitive,
+ )
+ }
+ } else {
+ listOf(packageOps)
}
} else {
listOf(packageOps)
}
- } else {
- listOf(packageOps)
}
}
.flatten()
@@ -147,7 +167,7 @@ class GetPermissionGroupUsageDetailsUseCase(
packageOps.userId,
currentCluster.toMutableList(),
packageOps.attributionLabel,
- packageOps.isUserSensitive
+ packageOps.isUserSensitive,
)
)
currentCluster.clear()
@@ -164,7 +184,7 @@ class GetPermissionGroupUsageDetailsUseCase(
packageOps.userId,
currentCluster.toMutableList(),
packageOps.attributionLabel,
- packageOps.isUserSensitive
+ packageOps.isUserSensitive,
)
)
}
@@ -220,7 +240,7 @@ class GetPermissionGroupUsageDetailsUseCase(
private fun canAccessBeAddedToCluster(
currentAccess: DiscreteOpModel,
- clusteredAccesses: List<DiscreteOpModel>
+ clusteredAccesses: List<DiscreteOpModel>,
): Boolean {
val clusterOp = clusteredAccesses.last().opName
if (
@@ -282,7 +302,7 @@ class GetPermissionGroupUsageDetailsUseCase(
listOf(
Manifest.permission_group.CAMERA,
Manifest.permission_group.LOCATION,
- Manifest.permission_group.MICROPHONE
+ Manifest.permission_group.MICROPHONE,
)
permissionGroups.forEach { permissionGroup ->
val opNames =
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/domain/usecase/GetPermissionGroupUsageDetailsUseCaseTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/domain/usecase/GetPermissionGroupUsageDetailsUseCaseTest.kt
index da2d05f63..c2040f76b 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/domain/usecase/GetPermissionGroupUsageDetailsUseCaseTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/domain/usecase/GetPermissionGroupUsageDetailsUseCaseTest.kt
@@ -34,6 +34,7 @@ import com.android.permissioncontroller.permission.domain.model.v31.PermissionTi
import com.android.permissioncontroller.permission.domain.model.v31.PermissionTimelineUsageModelWrapper
import com.android.permissioncontroller.permission.domain.usecase.v31.GetPermissionGroupUsageDetailsUseCase
import com.android.permissioncontroller.permission.domain.usecase.v31.TELECOM_PACKAGE
+import com.android.permissioncontroller.permission.utils.LocationUtils
import com.android.permissioncontroller.pm.data.model.v31.PackageAttributionModel
import com.android.permissioncontroller.pm.data.model.v31.PackageInfoModel
import com.android.permissioncontroller.pm.data.repository.v31.PackageRepository
@@ -56,9 +57,11 @@ import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Assume
import org.junit.Before
+import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
+import org.mockito.Mockito
import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
import org.mockito.MockitoSession
@@ -88,11 +91,13 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
mockitoSession =
ExtendedMockito.mockitoSession()
.mockStatic(PermissionControllerApplication::class.java)
+ .mockStatic(LocationUtils::class.java)
.strictness(Strictness.LENIENT)
.startMocking()
whenever(PermissionControllerApplication.get()).thenReturn(application)
whenever(application.applicationContext).thenReturn(context)
+ whenever(LocationUtils.isLocationProvider(Mockito.any(), Mockito.any())).thenReturn(false)
packageInfos =
mapOf(
@@ -102,7 +107,7 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
systemPackageName to
getPackageInfoModel(
systemPackageName,
- applicationFlags = ApplicationInfo.FLAG_SYSTEM
+ applicationFlags = ApplicationInfo.FLAG_SYSTEM,
),
)
.toMutableMap()
@@ -124,7 +129,7 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
emit(
listOf(
DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents),
- DiscretePackageOpsModel(guestUserPkgName, guestUser.identifier, appOpEvents)
+ DiscretePackageOpsModel(guestUserPkgName, guestUser.identifier, appOpEvents),
)
)
}
@@ -150,11 +155,7 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
emit(
listOf(
DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents),
- DiscretePackageOpsModel(
- testPackageName,
- privateProfile.identifier,
- appOpEvents
- ),
+ DiscretePackageOpsModel(testPackageName, privateProfile.identifier, appOpEvents),
)
)
}
@@ -168,8 +169,8 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
currentUserProfiles =
listOf(currentUser.identifier, privateProfile.identifier),
quietUserProfiles = listOf(privateProfile.identifier),
- showInQuiteModeProfiles = listOf(privateProfile.identifier)
- )
+ showInQuiteModeProfiles = listOf(privateProfile.identifier),
+ ),
)
val permissionTimelineUsages = getResult(underTest, this)
@@ -190,11 +191,7 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
emit(
listOf(
DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents),
- DiscretePackageOpsModel(
- testPackageName,
- privateProfile.identifier,
- appOpEvents
- ),
+ DiscretePackageOpsModel(testPackageName, privateProfile.identifier, appOpEvents),
)
)
}
@@ -208,7 +205,7 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
currentUserProfiles =
listOf(currentUser.identifier, privateProfile.identifier),
quietUserProfiles = listOf(privateProfile.identifier),
- )
+ ),
)
val permissionTimelineUsages = getResult(underTest, this)
@@ -254,7 +251,7 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
val discretePackageOps = flow {
emit(
listOf(
- DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents),
+ DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents)
)
)
}
@@ -280,7 +277,7 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
val discretePackageOps = flow {
emit(
listOf(
- DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents),
+ DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents)
)
)
}
@@ -303,23 +300,23 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
DiscreteOpModel(
AppOpsManager.OPSTR_CAMERA,
MINUTES.toMillis(1),
- MINUTES.toMillis(1)
+ MINUTES.toMillis(1),
),
DiscreteOpModel(
AppOpsManager.OPSTR_CAMERA,
MINUTES.toMillis(2),
- MINUTES.toMillis(1)
+ MINUTES.toMillis(1),
),
DiscreteOpModel(
AppOpsManager.OPSTR_CAMERA,
MINUTES.toMillis(3),
- MINUTES.toMillis(2)
+ MINUTES.toMillis(2),
),
)
val discretePackageOps = flow {
emit(
listOf(
- DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents),
+ DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents)
)
)
}
@@ -344,23 +341,19 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
DiscreteOpModel(
AppOpsManager.OPSTR_FINE_LOCATION,
hours3 + MINUTES.toMillis(59),
- -1
+ -1,
),
DiscreteOpModel(
AppOpsManager.OPSTR_FINE_LOCATION,
hours4 + MINUTES.toMillis(0),
- -1
- ),
- DiscreteOpModel(
- AppOpsManager.OPSTR_FINE_LOCATION,
- hours4 + MINUTES.toMillis(1),
- -1
+ -1,
),
+ DiscreteOpModel(AppOpsManager.OPSTR_FINE_LOCATION, hours4 + MINUTES.toMillis(1), -1),
)
val discretePackageOps = flow {
emit(
listOf(
- DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents),
+ DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents)
)
)
}
@@ -383,18 +376,18 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
DiscreteOpModel(
AppOpsManager.OPSTR_CAMERA,
MINUTES.toMillis(1),
- MINUTES.toMillis(3)
+ MINUTES.toMillis(3),
),
DiscreteOpModel(
AppOpsManager.OPSTR_CAMERA,
MINUTES.toMillis(3),
- MINUTES.toMillis(2)
+ MINUTES.toMillis(2),
),
)
val discretePackageOps = flow {
emit(
listOf(
- DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents),
+ DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents)
)
)
}
@@ -420,7 +413,7 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
val discretePackageOps = flow {
emit(
listOf(
- DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents),
+ DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents)
)
)
}
@@ -448,18 +441,18 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
DiscreteOpModel(
AppOpsManager.OPSTR_CAMERA,
MINUTES.toMillis(1),
- MINUTES.toMillis(3)
+ MINUTES.toMillis(3),
),
DiscreteOpModel(
AppOpsManager.OPSTR_CAMERA,
MINUTES.toMillis(5),
- MINUTES.toMillis(5)
+ MINUTES.toMillis(5),
),
)
val discretePackageOps = flow {
emit(
listOf(
- DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents),
+ DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents)
)
)
}
@@ -483,13 +476,11 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
@Test
fun singleDiscreteAccess() = runTest {
val appOpEvents =
- listOf(
- DiscreteOpModel(AppOpsManager.OPSTR_FINE_LOCATION, MINUTES.toMillis(1), -1),
- )
+ listOf(DiscreteOpModel(AppOpsManager.OPSTR_FINE_LOCATION, MINUTES.toMillis(1), -1))
val discretePackageOps = flow {
emit(
listOf(
- DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents),
+ DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents)
)
)
}
@@ -512,13 +503,13 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
DiscreteOpModel(
AppOpsManager.OPSTR_CAMERA,
MINUTES.toMillis(1),
- MINUTES.toMillis(3)
- ),
+ MINUTES.toMillis(3),
+ )
)
val discretePackageOps = flow {
emit(
listOf(
- DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents),
+ DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents)
)
)
}
@@ -541,29 +532,29 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
DiscreteOpModel(
AppOpsManager.OPSTR_CAMERA,
MINUTES.toMillis(1),
- MINUTES.toMillis(2)
+ MINUTES.toMillis(2),
),
// This entry says the camera was accessed for 15 minutes starting at minute 3
DiscreteOpModel(
AppOpsManager.OPSTR_CAMERA,
MINUTES.toMillis(3),
- MINUTES.toMillis(15)
+ MINUTES.toMillis(15),
),
DiscreteOpModel(
AppOpsManager.OPSTR_CAMERA,
MINUTES.toMillis(4),
- MINUTES.toMillis(1)
+ MINUTES.toMillis(1),
),
DiscreteOpModel(
AppOpsManager.OPSTR_CAMERA,
MINUTES.toMillis(6),
- MINUTES.toMillis(1)
+ MINUTES.toMillis(1),
),
)
val discretePackageOps = flow {
emit(
listOf(
- DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents),
+ DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents)
)
)
}
@@ -582,9 +573,7 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
@Test
fun verifyUserSensitiveFlags() = runTest {
val appOpEvents =
- listOf(
- DiscreteOpModel(AppOpsManager.OPSTR_COARSE_LOCATION, MINUTES.toMillis(1), -1),
- )
+ listOf(DiscreteOpModel(AppOpsManager.OPSTR_COARSE_LOCATION, MINUTES.toMillis(1), -1))
val discretePackageOps = flow {
emit(
listOf(
@@ -620,13 +609,11 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
@Test
fun verifyNotUserSensitiveFlagsForSystemPackage() = runTest {
val appOpEvents =
- listOf(
- DiscreteOpModel(AppOpsManager.OPSTR_COARSE_LOCATION, MINUTES.toMillis(1), -1),
- )
+ listOf(DiscreteOpModel(AppOpsManager.OPSTR_COARSE_LOCATION, MINUTES.toMillis(1), -1))
val discretePackageOps = flow {
emit(
listOf(
- DiscretePackageOpsModel(systemPackageName, currentUser.identifier, appOpEvents),
+ DiscretePackageOpsModel(systemPackageName, currentUser.identifier, appOpEvents)
)
)
}
@@ -651,14 +638,12 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
@Test
fun verifyCameraUserSensitiveFlagsForTelecomPackage() = runTest {
val appOpEvents =
- listOf(
- DiscreteOpModel(AppOpsManager.OPSTR_CAMERA, MINUTES.toMillis(1), -1),
- )
+ listOf(DiscreteOpModel(AppOpsManager.OPSTR_CAMERA, MINUTES.toMillis(1), -1))
packageInfos[TELECOM_PACKAGE] = getPackageInfoModel(TELECOM_PACKAGE)
val discretePackageOps = flow {
emit(
listOf(
- DiscretePackageOpsModel(TELECOM_PACKAGE, currentUser.identifier, appOpEvents),
+ DiscretePackageOpsModel(TELECOM_PACKAGE, currentUser.identifier, appOpEvents)
)
)
}
@@ -683,14 +668,12 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
@Test
fun verifyLocationUserSensitiveFlagsForTelecomPackage() = runTest {
val appOpEvents =
- listOf(
- DiscreteOpModel(AppOpsManager.OPSTR_COARSE_LOCATION, MINUTES.toMillis(1), -1),
- )
+ listOf(DiscreteOpModel(AppOpsManager.OPSTR_COARSE_LOCATION, MINUTES.toMillis(1), -1))
packageInfos[TELECOM_PACKAGE] = getPackageInfoModel(TELECOM_PACKAGE)
val discretePackageOps = flow {
emit(
listOf(
- DiscretePackageOpsModel(TELECOM_PACKAGE, currentUser.identifier, appOpEvents),
+ DiscretePackageOpsModel(TELECOM_PACKAGE, currentUser.identifier, appOpEvents)
)
)
}
@@ -714,7 +697,74 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
}
@Test
- fun verifyAttributionTagsAreGroupedAndClustered() = runTest {
+ @RequiresFlagsEnabled(
+ com.android.permission.flags.Flags.FLAG_PERMISSION_TIMELINE_ATTRIBUTION_LABEL_FIX
+ )
+ @Ignore("b/365004787")
+ fun verifyAccessIsNotGroupedByAttributionLabelAndClustered() = runTest {
+ // The package is not a location provider.
+ val appOpEvents =
+ listOf(
+ // These entries should be clustered even though they have
+ // different attribution labels.
+ DiscreteOpModel(
+ AppOpsManager.OPSTR_COARSE_LOCATION,
+ MINUTES.toMillis(1),
+ -1,
+ "tag1",
+ ),
+ DiscreteOpModel(
+ AppOpsManager.OPSTR_COARSE_LOCATION,
+ MINUTES.toMillis(2),
+ -1,
+ "tag1",
+ ),
+ DiscreteOpModel(
+ AppOpsManager.OPSTR_COARSE_LOCATION,
+ MINUTES.toMillis(3),
+ -1,
+ "tag3",
+ ),
+ DiscreteOpModel(
+ AppOpsManager.OPSTR_COARSE_LOCATION,
+ MINUTES.toMillis(4),
+ -1,
+ "tag2",
+ ),
+ )
+ val discretePackageOps = flow {
+ emit(
+ listOf(
+ DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents)
+ )
+ )
+ }
+ val packageAttributions = mutableMapOf<String, PackageAttributionModel>()
+ // tag1 and tag3 refers to same attribution label.
+ val attributionTagToLabelRes = mapOf("tag1" to 100, "tag2" to 200, "tag3" to 100)
+ val attributionsMap = mapOf(100 to "Tag1 Label", 200 to "Tag2 Label")
+ packageAttributions[testPackageName] =
+ PackageAttributionModel(
+ testPackageName,
+ true,
+ attributionTagToLabelRes,
+ attributionsMap,
+ )
+
+ val underTest =
+ getPermissionGroupUsageDetailsUseCase(
+ LOCATION_PERMISSION_GROUP,
+ discretePackageOps,
+ packageRepository = FakePackageRepository(packageInfos, packageAttributions),
+ )
+ val permissionTimelineUsages = getResult(underTest, this)
+
+ Truth.assertThat(permissionTimelineUsages.size).isEqualTo(1)
+ }
+
+ @Test
+ fun verifyAccessIsGroupedByAttributionLabelAndClustered() = runTest {
+ whenever(LocationUtils.isLocationProvider(Mockito.any(), Mockito.any())).thenReturn(true)
val appOpEvents =
listOf(
// These 3 entries should be grouped and clustered.
@@ -722,38 +772,38 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
AppOpsManager.OPSTR_COARSE_LOCATION,
MINUTES.toMillis(1),
-1,
- "tag1"
+ "tag1",
),
DiscreteOpModel(
AppOpsManager.OPSTR_COARSE_LOCATION,
MINUTES.toMillis(2),
-1,
- "tag1"
+ "tag1",
),
DiscreteOpModel(
AppOpsManager.OPSTR_COARSE_LOCATION,
MINUTES.toMillis(3),
-1,
- "tag3"
+ "tag3",
),
// The access at minute 4 should not be grouped or clustered.
DiscreteOpModel(
AppOpsManager.OPSTR_COARSE_LOCATION,
MINUTES.toMillis(4),
-1,
- "tag2"
+ "tag2",
),
DiscreteOpModel(
AppOpsManager.OPSTR_COARSE_LOCATION,
MINUTES.toMillis(8),
-1,
- "tag2"
+ "tag2",
),
)
val discretePackageOps = flow {
emit(
listOf(
- DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents),
+ DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents)
)
)
}
@@ -766,14 +816,14 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
testPackageName,
true,
attributionTagToLabelRes,
- attributionsMap
+ attributionsMap,
)
val underTest =
getPermissionGroupUsageDetailsUseCase(
LOCATION_PERMISSION_GROUP,
discretePackageOps,
- packageRepository = FakePackageRepository(packageInfos, packageAttributions)
+ packageRepository = FakePackageRepository(packageInfos, packageAttributions),
)
val permissionTimelineUsages = getResult(underTest, this)
@@ -805,7 +855,7 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
val discretePackageOps = flow {
emit(
listOf(
- DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents),
+ DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents)
)
)
}
@@ -829,7 +879,7 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
val discretePackageOps = flow {
emit(
listOf(
- DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents),
+ DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents)
)
)
}
@@ -843,7 +893,7 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
private fun TestScope.getResult(
useCase: GetPermissionGroupUsageDetailsUseCase,
- coroutineScope: CoroutineScope
+ coroutineScope: CoroutineScope,
): List<PermissionTimelineUsageModel> {
val usages by collectLastValue(useCase(coroutineScope))
return (usages as PermissionTimelineUsageModelWrapper.Success).timelineUsageModels
@@ -854,7 +904,7 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
discreteUsageFlow: Flow<List<DiscretePackageOpsModel>>,
permissionFlags: Map<String, Int> = emptyMap(),
userRepository: UserRepository = FakeUserRepository(listOf(currentUser.identifier)),
- packageRepository: PackageRepository = FakePackageRepository(packageInfos)
+ packageRepository: PackageRepository = FakePackageRepository(packageInfos),
): GetPermissionGroupUsageDetailsUseCase {
val permissionRepository = FakePermissionRepository(permissionFlags)
val appOpUsageRepository = FakeAppOpRepository(emptyFlow(), discreteUsageFlow)
@@ -865,7 +915,7 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
permissionRepository,
appOpUsageRepository,
roleRepository,
- userRepository
+ userRepository,
)
}
@@ -877,7 +927,7 @@ class GetPermissionGroupUsageDetailsUseCaseTest {
listOf(
PackageInfo.REQUESTED_PERMISSION_GRANTED,
PackageInfo.REQUESTED_PERMISSION_GRANTED,
- PackageInfo.REQUESTED_PERMISSION_GRANTED
+ PackageInfo.REQUESTED_PERMISSION_GRANTED,
),
applicationFlags: Int = 0,
) = PackageInfoModel(packageName, requestedPermissions, permissionsFlags, applicationFlags)
diff --git a/flags/Android.bp b/flags/Android.bp
index aba1e44a9..d22da26c3 100644
--- a/flags/Android.bp
+++ b/flags/Android.bp
@@ -36,6 +36,7 @@ java_aconfig_library {
libs: ["framework-configinfrastructure.stubs.module_lib"],
visibility: [
"//packages/modules/Permission:__subpackages__",
+ "//vendor:__subpackages__",
],
apex_available: [
"com.android.permission",
diff --git a/flags/flags.aconfig b/flags/flags.aconfig
index c94614654..5f3d1cc93 100644
--- a/flags/flags.aconfig
+++ b/flags/flags.aconfig
@@ -108,3 +108,12 @@ flag {
bug: "349675008"
is_fixed_read_only: true
}
+
+flag {
+ name: "permission_timeline_attribution_label_fix"
+ is_exported: true
+ namespace: "permissions"
+ description: "This flag is used for the attribution label fix on permission timeline page"
+ bug: "369606734"
+ is_fixed_read_only: true
+}