diff options
author | 2023-04-19 18:26:48 +0000 | |
---|---|---|
committer | 2023-04-19 18:26:48 +0000 | |
commit | 10a6e8e3b35f8ca69ef0da0e2c5b85384d06e4d3 (patch) | |
tree | a5b55e8156342db3f0673a04b6a3f8b68f34e9f8 | |
parent | b352be1f23628a51967aa327f5697829f7479853 (diff) | |
parent | 6a048cbbf5f4eb6e956368cc04a6152aa52b39b6 (diff) |
Merge "[Safety Labels] Optimisation and testing for safety labels persistence" into udc-dev
4 files changed, 204 insertions, 72 deletions
diff --git a/PermissionController/src/com/android/permissioncontroller/safetylabel/AppsSafetyLabelHistoryPersistence.kt b/PermissionController/src/com/android/permissioncontroller/safetylabel/AppsSafetyLabelHistoryPersistence.kt index 24fb90cbb..9bb7e819f 100644 --- a/PermissionController/src/com/android/permissioncontroller/safetylabel/AppsSafetyLabelHistoryPersistence.kt +++ b/PermissionController/src/com/android/permissioncontroller/safetylabel/AppsSafetyLabelHistoryPersistence.kt @@ -67,12 +67,12 @@ object AppsSafetyLabelHistoryPersistence { /** Adds a listener to listen for changes to persisted safety labels. */ fun addListener(listener: ChangeListener) { - listeners.add(listener) + synchronized(readWriteLock) { listeners.add(listener) } } /** Removes a listener from listening for changes to persisted safety labels. */ fun removeListener(listener: ChangeListener) { - listeners.remove(listener) + synchronized(readWriteLock) { listeners.remove(listener) } } /** @@ -101,18 +101,20 @@ object AppsSafetyLabelHistoryPersistence { /** Returns the last updated time for each stored [AppSafetyLabelHistory]. */ fun getSafetyLabelsLastUpdatedTimes(file: File): Map<AppInfo, Instant> { - val appHistories = - read(file).appsSafetyLabelHistory?.appSafetyLabelHistories ?: return emptyMap() - - val lastUpdatedTimes = mutableMapOf<AppInfo, Instant>() - for (appHistory in appHistories) { - val lastSafetyLabelReceiptTime: Instant? = appHistory.getLastReceiptTime() - if (lastSafetyLabelReceiptTime != null) { - lastUpdatedTimes[appHistory.appInfo] = lastSafetyLabelReceiptTime + synchronized(readWriteLock) { + val appHistories = + read(file).appsSafetyLabelHistory?.appSafetyLabelHistories ?: return emptyMap() + + val lastUpdatedTimes = mutableMapOf<AppInfo, Instant>() + for (appHistory in appHistories) { + val lastSafetyLabelReceiptTime: Instant? = appHistory.getLastReceiptTime() + if (lastSafetyLabelReceiptTime != null) { + lastUpdatedTimes[appHistory.appInfo] = lastSafetyLabelReceiptTime + } } - } - return lastUpdatedTimes + return lastUpdatedTimes + } } /** @@ -149,6 +151,8 @@ object AppsSafetyLabelHistoryPersistence { * from the last recorded (when considered in order of [SafetyLabel.receivedAt]). */ fun recordSafetyLabels(safetyLabelsToAdd: Set<SafetyLabel>, file: File) { + if (safetyLabelsToAdd.isEmpty()) return + synchronized(readWriteLock) { val currentAppsSafetyLabelHistory = read(file).appsSafetyLabelHistory ?: AppsSafetyLabelHistory(listOf()) @@ -190,6 +194,8 @@ object AppsSafetyLabelHistoryPersistence { /** Deletes stored safety labels for all apps in [appInfosToRemove]. */ fun deleteSafetyLabelsForApps(appInfosToRemove: Set<AppInfo>, file: File) { + if (appInfosToRemove.isEmpty()) return + synchronized(readWriteLock) { val currentAppsSafetyLabelHistory = read(file).appsSafetyLabelHistory ?: AppsSafetyLabelHistory(listOf()) diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/AppsSafetyLabelHistoryPersistenceTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/AppsSafetyLabelHistoryPersistenceTest.kt index f853560fd..10221f6fa 100644 --- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/AppsSafetyLabelHistoryPersistenceTest.kt +++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/AppsSafetyLabelHistoryPersistenceTest.kt @@ -27,15 +27,26 @@ import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistory import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistory.AppInfo import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistory.AppSafetyLabelDiff import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistory.AppSafetyLabelHistory -import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistory.DataCategory -import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistory.DataLabel -import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistory.SafetyLabel import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistoryPersistence import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistoryPersistence.AppsSafetyLabelHistoryFileContent import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistoryPersistence.ChangeListener +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.DATE_2022_10_10 +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.DATE_2022_10_12 +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.DATE_2022_10_14 +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.DATE_2022_12_10 +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.DATE_2022_12_30 +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.PACKAGE_NAME_1 +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.PACKAGE_NAME_2 +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.PACKAGE_NAME_3 +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.SAFETY_LABEL_PKG_1_V1 +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.SAFETY_LABEL_PKG_1_V2 +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.SAFETY_LABEL_PKG_1_V3 +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.SAFETY_LABEL_PKG_2_V1 +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.SAFETY_LABEL_PKG_2_V2 +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.SAFETY_LABEL_PKG_2_V3 +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.SAFETY_LABEL_PKG_3_V1 import com.google.common.truth.Truth.assertThat import java.io.File -import java.time.ZonedDateTime import org.junit.After import org.junit.Before import org.junit.Test @@ -323,6 +334,23 @@ class AppsSafetyLabelHistoryPersistenceTest { } @Test + fun getAppSafetyLabelDiffs_whenNoSafetyLabelsBeforeStartTime_returnsMoreRecentDiffs() { + val appsSafetyLabelHistory = + AppsSafetyLabelHistory( + listOf( + AppSafetyLabelHistory( + AppInfo(PACKAGE_NAME_2), + listOf(SAFETY_LABEL_PKG_2_V2, SAFETY_LABEL_PKG_2_V3)))) + AppsSafetyLabelHistoryPersistence.write(dataFile, appsSafetyLabelHistory) + + val safetyLabelDiffs: List<AppSafetyLabelDiff> = + AppsSafetyLabelHistoryPersistence.getAppSafetyLabelDiffs(DATE_2022_10_10, dataFile) + + assertThat(safetyLabelDiffs) + .isEqualTo(listOf(AppSafetyLabelDiff(SAFETY_LABEL_PKG_2_V2, SAFETY_LABEL_PKG_2_V3))) + } + + @Test fun getAppSafetyLabelDiffs_returnsAvailableDiffs() { val appsSafetyLabelHistory = AppsSafetyLabelHistory( @@ -347,7 +375,7 @@ class AppsSafetyLabelHistoryPersistenceTest { } @Test - fun givenNoAppsPersisted_getSafetyLabelsLastUpdatedTimes_returnsEmptyMap() { + fun getSafetyLabelsLastUpdatedTimes_noAppsPersisted_returnsEmptyMap() { val lastUpdatedTimes = AppsSafetyLabelHistoryPersistence.getSafetyLabelsLastUpdatedTimes(dataFile) @@ -355,7 +383,7 @@ class AppsSafetyLabelHistoryPersistenceTest { } @Test - fun givenSomeAppsPersisted_getSafetyLabelsLastUpdatedTimes_returnsLastUpdatedTimes() { + fun getSafetyLabelsLastUpdatedTimes_appsPersisted_returnsLastUpdatedTimes() { val appsSafetyLabelHistory = AppsSafetyLabelHistory( listOf( @@ -494,60 +522,6 @@ class AppsSafetyLabelHistoryPersistenceTest { companion object { private const val TEST_FILE_NAME = "test_safety_label_history_file" - private const val PACKAGE_NAME_1 = "package_name_1" - private const val PACKAGE_NAME_2 = "package_name_2" - private const val PACKAGE_NAME_3 = "package_name_3" - private const val LOCATION_CATEGORY = "location" - private const val FINANCIAL_CATEGORY = "financial" - private val DATE_2022_09_01 = ZonedDateTime.parse("2022-09-01T00:00:00.000Z").toInstant() - private val DATE_2022_10_10 = ZonedDateTime.parse("2022-10-10T00:00:00.000Z").toInstant() - private val DATE_2022_10_12 = ZonedDateTime.parse("2022-10-12T00:00:00.000Z").toInstant() - private val DATE_2022_10_14 = ZonedDateTime.parse("2022-10-14T00:00:00.000Z").toInstant() - private val DATE_2022_12_10 = ZonedDateTime.parse("2022-12-10T00:00:00.000Z").toInstant() - private val DATE_2022_12_30 = ZonedDateTime.parse("2022-12-30T00:00:00.000Z").toInstant() - - private val SAFETY_LABEL_PKG_1_V1 = - SafetyLabel( - AppInfo(PACKAGE_NAME_1), - DATE_2022_09_01, - DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(true)))) - - private val SAFETY_LABEL_PKG_1_V2 = - SafetyLabel( - AppInfo(PACKAGE_NAME_1), - DATE_2022_10_14, - DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(false)))) - - private val SAFETY_LABEL_PKG_1_V3 = - SafetyLabel( - AppInfo(PACKAGE_NAME_1), - DATE_2022_12_10, - DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(false)))) - - private val SAFETY_LABEL_PKG_2_V1 = - SafetyLabel( - AppInfo(PACKAGE_NAME_2), - DATE_2022_10_10, - DataLabel( - mapOf( - LOCATION_CATEGORY to DataCategory(true), - FINANCIAL_CATEGORY to DataCategory(false)))) - - private val SAFETY_LABEL_PKG_2_V2 = - SafetyLabel(AppInfo(PACKAGE_NAME_2), DATE_2022_12_10, DataLabel(mapOf())) - - private val SAFETY_LABEL_PKG_2_V3 = - SafetyLabel( - AppInfo(PACKAGE_NAME_2), - DATE_2022_12_30, - DataLabel(mapOf(FINANCIAL_CATEGORY to DataCategory(true)))) - - private val SAFETY_LABEL_PKG_3_V1 = - SafetyLabel( - AppInfo(PACKAGE_NAME_3), - DATE_2022_10_10, - DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(true)))) - private const val PROPERTY_MAX_SAFETY_LABELS_PERSISTED_PER_APP = "max_safety_labels_persisted_per_app" diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/AppsSafetyLabelHistoryTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/AppsSafetyLabelHistoryTest.kt index 48891e9c7..dedb0b1cd 100644 --- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/AppsSafetyLabelHistoryTest.kt +++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/AppsSafetyLabelHistoryTest.kt @@ -23,16 +23,80 @@ import com.android.permission.safetylabel.SafetyLabel as AppMetadataSafetyLabel import com.android.permission.safetylabel.SafetyLabel.KEY_VERSION import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistory import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistory.AppInfo +import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistory.AppSafetyLabelHistory import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistory.DataCategory import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistory.DataLabel import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistory.SafetyLabel +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.DATE_2022_09_01 +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.DATE_2022_10_10 +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.LOCATION_CATEGORY +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.PACKAGE_NAME_1 +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.PACKAGE_NAME_2 +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.SAFETY_LABEL_PKG_1_V1 +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.SAFETY_LABEL_PKG_1_V2 +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.SAFETY_LABEL_PKG_1_V3 +import com.android.permissioncontroller.tests.mocking.safetylabel.TestSafetyLabels.SAFETY_LABEL_PKG_2_V1 import com.google.common.truth.Truth.assertThat import java.time.ZonedDateTime +import org.junit.Assert import org.junit.Test /** Tests for [AppsSafetyLabelHistory]. */ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake") class AppsSafetyLabelHistoryTest { + + @Test + fun createAppSafetyLabelHistory_requiresAllSafetyLabelsHaveSameApp() { + Assert.assertThrows(IllegalArgumentException::class.java) { + AppSafetyLabelHistory( + AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_2_V1)) + } + } + + @Test + fun createAppSafetyLabelHistory_requiresOrderedByReceivedAt() { + Assert.assertThrows(IllegalArgumentException::class.java) { + AppSafetyLabelHistory( + AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V2, SAFETY_LABEL_PKG_1_V1)) + } + } + + @Test + fun withSafetyLabel_forDifferentApp_throwsIllegalArgumentException() { + val appSafetyLabelHistory = + AppSafetyLabelHistory( + AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V3)) + + Assert.assertThrows(IllegalArgumentException::class.java) { + appSafetyLabelHistory.withSafetyLabel(SAFETY_LABEL_PKG_2_V1, 20) + } + } + + @Test + fun withSafetyLabel_returnsOrderdSafetyLabels() { + val appSafetyLabelHistory = + AppSafetyLabelHistory( + AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V3)) + + assertThat(appSafetyLabelHistory.withSafetyLabel(SAFETY_LABEL_PKG_1_V2, 20)) + .isEqualTo( + AppSafetyLabelHistory( + AppInfo(PACKAGE_NAME_1), + listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V2, SAFETY_LABEL_PKG_1_V3))) + } + + @Test + fun withSafetyLabel_dropsOldLabelsWhenMaxPersisted() { + val appSafetyLabelHistory = + AppSafetyLabelHistory( + AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V1, SAFETY_LABEL_PKG_1_V3)) + + assertThat(appSafetyLabelHistory.withSafetyLabel(SAFETY_LABEL_PKG_1_V2, 2)) + .isEqualTo( + AppSafetyLabelHistory( + AppInfo(PACKAGE_NAME_1), listOf(SAFETY_LABEL_PKG_1_V2, SAFETY_LABEL_PKG_1_V3))) + } + @Test fun extractLocationSharingSafetyLabel_noSharing_returnsSafetyLabelForPersistence() { val metadataBundle = createMetadataWithDataShared(createDataSharedNoSharing()) diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/TestSafetyLabels.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/TestSafetyLabels.kt new file mode 100644 index 000000000..19c5adddd --- /dev/null +++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetylabel/TestSafetyLabels.kt @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2023 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.permissioncontroller.tests.mocking.safetylabel + +import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistory.AppInfo +import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistory.DataCategory +import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistory.DataLabel +import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistory.SafetyLabel +import java.time.Instant +import java.time.ZonedDateTime + +/** Safety labels to be used in tests. */ +object TestSafetyLabels { + const val PACKAGE_NAME_1 = "package_name_1" + const val PACKAGE_NAME_2 = "package_name_2" + const val PACKAGE_NAME_3 = "package_name_3" + const val LOCATION_CATEGORY = "location" + const val FINANCIAL_CATEGORY = "financial" + val DATE_2022_09_01: Instant = ZonedDateTime.parse("2022-09-01T00:00:00.000Z").toInstant() + val DATE_2022_10_10: Instant = ZonedDateTime.parse("2022-10-10T00:00:00.000Z").toInstant() + val DATE_2022_10_12: Instant = ZonedDateTime.parse("2022-10-12T00:00:00.000Z").toInstant() + val DATE_2022_10_14: Instant = ZonedDateTime.parse("2022-10-14T00:00:00.000Z").toInstant() + val DATE_2022_12_10: Instant = ZonedDateTime.parse("2022-12-10T00:00:00.000Z").toInstant() + val DATE_2022_12_30: Instant = ZonedDateTime.parse("2022-12-30T00:00:00.000Z").toInstant() + + /** A Safety label for [PACKAGE_NAME_1]. */ + val SAFETY_LABEL_PKG_1_V1: SafetyLabel = + SafetyLabel( + AppInfo(PACKAGE_NAME_1), + DATE_2022_09_01, + DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(true)))) + + /** A Safety label for [PACKAGE_NAME_1]. */ + val SAFETY_LABEL_PKG_1_V2: SafetyLabel = + SafetyLabel( + AppInfo(PACKAGE_NAME_1), + DATE_2022_10_14, + DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(false)))) + + /** A Safety label for [PACKAGE_NAME_1]. */ + val SAFETY_LABEL_PKG_1_V3: SafetyLabel = + SafetyLabel( + AppInfo(PACKAGE_NAME_1), + DATE_2022_12_10, + DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(false)))) + + /** A Safety label for [PACKAGE_NAME_2]. */ + val SAFETY_LABEL_PKG_2_V1: SafetyLabel = + SafetyLabel( + AppInfo(PACKAGE_NAME_2), + DATE_2022_10_10, + DataLabel( + mapOf( + LOCATION_CATEGORY to DataCategory(true), + FINANCIAL_CATEGORY to DataCategory(false)))) + + /** A Safety label for [PACKAGE_NAME_2]. */ + val SAFETY_LABEL_PKG_2_V2: SafetyLabel = + SafetyLabel(AppInfo(PACKAGE_NAME_2), DATE_2022_12_10, DataLabel(mapOf())) + + /** A Safety label for [PACKAGE_NAME_2]. */ + val SAFETY_LABEL_PKG_2_V3: SafetyLabel = + SafetyLabel( + AppInfo(PACKAGE_NAME_2), + DATE_2022_12_30, + DataLabel(mapOf(FINANCIAL_CATEGORY to DataCategory(true)))) + + /** A Safety label for [PACKAGE_NAME_3]. */ + val SAFETY_LABEL_PKG_3_V1: SafetyLabel = + SafetyLabel( + AppInfo(PACKAGE_NAME_3), + DATE_2022_10_10, + DataLabel(mapOf(LOCATION_CATEGORY to DataCategory(true)))) +} |