diff --git a/src/com/android/settings/datausage/lib/AppDataUsageRepository.kt b/src/com/android/settings/datausage/lib/AppDataUsageRepository.kt index 0055463fb27..6ed9f7c3ab4 100644 --- a/src/com/android/settings/datausage/lib/AppDataUsageRepository.kt +++ b/src/com/android/settings/datausage/lib/AppDataUsageRepository.kt @@ -28,6 +28,7 @@ import android.util.SparseArray import android.util.SparseBooleanArray import androidx.annotation.VisibleForTesting import androidx.core.util.keyIterator +import androidx.core.util.valueIterator import com.android.settings.R import com.android.settings.datausage.lib.NetworkStatsRepository.Companion.Bucket import com.android.settingslib.AppItem @@ -49,33 +50,30 @@ class AppDataUsageRepository( @VisibleForTesting fun getAppPercent(carrierId: Int?, buckets: List): List> { - val items = ArrayList() val knownItems = SparseArray() val profiles = context.userManager.userProfiles val userManager : UserManager = context.getSystemService(Context.USER_SERVICE) as UserManager val userIdToIsHiddenMap = profiles.associate { profile -> profile.identifier to shouldSkipProfile(userManager, profile) } - bindStats(buckets, userIdToIsHiddenMap, knownItems, items) + bindStats(buckets, userIdToIsHiddenMap, knownItems) val restrictedUids = context.getSystemService(NetworkPolicyManager::class.java)!! .getUidsWithPolicy(NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND) for (uid in restrictedUids) { // Only splice in restricted state for current user or managed users - if (!profiles.contains(UserHandle.getUserHandleForUid(uid))) { - continue - } - var item = knownItems[uid] - if (item == null) { - item = AppItem(uid) - item.total = 0 - item.addUid(uid) - items.add(item) - knownItems.put(item.key, item) - } + if (UserHandle.getUserHandleForUid(uid) !in profiles) continue + val item = + knownItems[uid] + ?: AppItem(uid).apply { + category = AppItem.CATEGORY_APP + addUid(uid) + knownItems.put(uid, this) + } item.restricted = true } - val filteredItems = filterItems(carrierId, items).sorted() + val filteredItems = + filterItems(carrierId, knownItems.valueIterator().asSequence().toList()).sorted() val largest: Long = filteredItems.maxOfOrNull { it.total } ?: 0 return filteredItems.map { item -> val percentTotal = if (largest > 0) (item.total * 100 / largest).toInt() else 0 @@ -106,7 +104,6 @@ class AppDataUsageRepository( buckets: List, userIdToIsHiddenMap: Map, knownItems: SparseArray, - items: ArrayList, ) { for (bucket in buckets) { // Decide how to collapse items together @@ -126,7 +123,6 @@ class AppDataUsageRepository( knownItems = knownItems, bucket = bucket, itemCategory = AppItem.CATEGORY_USER, - items = items, ) } collapseKey = getAppUid(uid) @@ -157,7 +153,6 @@ class AppDataUsageRepository( knownItems = knownItems, bucket = bucket, itemCategory = category, - items = items, ) } } @@ -187,15 +182,13 @@ class AppDataUsageRepository( knownItems: SparseArray, bucket: Bucket, itemCategory: Int, - items: ArrayList, ) { - var item = knownItems[collapseKey] - if (item == null) { - item = AppItem(collapseKey) - item.category = itemCategory - items.add(item) - knownItems.put(item.key, item) - } + val item = + knownItems[collapseKey] + ?: AppItem(collapseKey).apply { + category = itemCategory + knownItems.put(collapseKey, this) + } item.addUid(bucket.uid) item.total += bucket.bytes } diff --git a/tests/spa_unit/src/com/android/settings/datausage/lib/AppDataUsageRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/datausage/lib/AppDataUsageRepositoryTest.kt index 3f517a96a33..5026b08fcf2 100644 --- a/tests/spa_unit/src/com/android/settings/datausage/lib/AppDataUsageRepositoryTest.kt +++ b/tests/spa_unit/src/com/android/settings/datausage/lib/AppDataUsageRepositoryTest.kt @@ -38,48 +38,55 @@ import org.mockito.junit.MockitoRule import org.mockito.kotlin.doReturn import org.mockito.kotlin.mock import org.mockito.kotlin.spy +import org.mockito.kotlin.stub @RunWith(AndroidJUnit4::class) class AppDataUsageRepositoryTest { - @get:Rule - val mockito: MockitoRule = MockitoJUnit.rule() + @get:Rule val mockito: MockitoRule = MockitoJUnit.rule() - private val mockUserManager = mock { - on { userProfiles } doReturn listOf(UserHandle.of(USER_ID)) - on { getUserInfo(USER_ID) } doReturn UserInfo(USER_ID, "", 0) - } + private val mockUserManager = + mock { + on { userProfiles } doReturn listOf(UserHandle.of(USER_ID)) + on { getUserInfo(USER_ID) } doReturn UserInfo(USER_ID, "", 0) + } - private val mockNetworkPolicyManager = mock { - on { getUidsWithPolicy(NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND) } doReturn - intArrayOf() - } + private val mockNetworkPolicyManager = + mock { + on { getUidsWithPolicy(NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND) } doReturn + intArrayOf() + } - private val mockResources = mock { - on { getIntArray(R.array.datausage_hiding_carrier_service_carrier_id) } doReturn - intArrayOf(HIDING_CARRIER_ID) + private val mockResources = + mock { + on { getIntArray(R.array.datausage_hiding_carrier_service_carrier_id) } doReturn + intArrayOf(HIDING_CARRIER_ID) - on { getStringArray(R.array.datausage_hiding_carrier_service_package_names) } doReturn - arrayOf(HIDING_PACKAGE_NAME) - } + on { getStringArray(R.array.datausage_hiding_carrier_service_package_names) } doReturn + arrayOf(HIDING_PACKAGE_NAME) + } - private val context: Context = spy(ApplicationProvider.getApplicationContext()) { - on { userManager } doReturn mockUserManager - on { getSystemService(NetworkPolicyManager::class.java) } doReturn mockNetworkPolicyManager - on { resources } doReturn mockResources - } + private val context: Context = + spy(ApplicationProvider.getApplicationContext()) { + on { userManager } doReturn mockUserManager + on { getSystemService(NetworkPolicyManager::class.java) } doReturn + mockNetworkPolicyManager + on { resources } doReturn mockResources + } @Test fun getAppPercent_noAppToHide() { - val repository = AppDataUsageRepository( - context = context, - currentUserId = USER_ID, - template = Template, - getPackageName = { null }, - ) - val buckets = listOf( - Bucket(uid = APP_ID_1, bytes = 1, startTimeStamp = 0, endTimeStamp = 0), - Bucket(uid = APP_ID_2, bytes = 2, startTimeStamp = 0, endTimeStamp = 0), - ) + val repository = + AppDataUsageRepository( + context = context, + currentUserId = USER_ID, + template = Template, + getPackageName = { null }, + ) + val buckets = + listOf( + Bucket(uid = APP_ID_1, bytes = 1, startTimeStamp = 0, endTimeStamp = 0), + Bucket(uid = APP_ID_2, bytes = 2, startTimeStamp = 0, endTimeStamp = 0), + ) val appPercentList = repository.getAppPercent(null, buckets) @@ -100,16 +107,18 @@ class AppDataUsageRepositoryTest { @Test fun getAppPercent_hasAppToHide() { - val repository = AppDataUsageRepository( - context = context, - currentUserId = USER_ID, - template = Template, - getPackageName = { if (it.key == APP_ID_1) HIDING_PACKAGE_NAME else null }, - ) - val buckets = listOf( - Bucket(uid = APP_ID_1, bytes = 1, startTimeStamp = 0, endTimeStamp = 0), - Bucket(uid = APP_ID_2, bytes = 2, startTimeStamp = 0, endTimeStamp = 0), - ) + val repository = + AppDataUsageRepository( + context = context, + currentUserId = USER_ID, + template = Template, + getPackageName = { if (it.key == APP_ID_1) HIDING_PACKAGE_NAME else null }, + ) + val buckets = + listOf( + Bucket(uid = APP_ID_1, bytes = 1, startTimeStamp = 0, endTimeStamp = 0), + Bucket(uid = APP_ID_2, bytes = 2, startTimeStamp = 0, endTimeStamp = 0), + ) val appPercentList = repository.getAppPercent(HIDING_CARRIER_ID, buckets) @@ -122,6 +131,43 @@ class AppDataUsageRepositoryTest { assertThat(appPercentList[0].second).isEqualTo(100) } + @Test + fun getAppPercent_restricted() { + mockNetworkPolicyManager.stub { + on { getUidsWithPolicy(NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND) } doReturn + intArrayOf(APP_ID_1) + } + val repository = + AppDataUsageRepository( + context = context, + currentUserId = USER_ID, + template = Template, + getPackageName = { null }, + ) + val buckets = + listOf( + Bucket(uid = APP_ID_2, bytes = 2, startTimeStamp = 0, endTimeStamp = 0), + ) + + val appPercentList = repository.getAppPercent(null, buckets) + + assertThat(appPercentList).hasSize(2) + appPercentList[0].first.apply { + assertThat(key).isEqualTo(APP_ID_2) + assertThat(category).isEqualTo(AppItem.CATEGORY_APP) + assertThat(total).isEqualTo(2) + assertThat(restricted).isFalse() + } + assertThat(appPercentList[0].second).isEqualTo(100) + appPercentList[1].first.apply { + assertThat(key).isEqualTo(APP_ID_1) + assertThat(category).isEqualTo(AppItem.CATEGORY_APP) + assertThat(total).isEqualTo(0) + assertThat(restricted).isTrue() + } + assertThat(appPercentList[1].second).isEqualTo(0) + } + private companion object { const val USER_ID = 1 const val APP_ID_1 = 110001