• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.permissioncontroller.safetylabel
18 
19 import com.android.permission.safetylabel.DataCategory as AppMetadataDataCategory
20 import com.android.permission.safetylabel.DataCategoryConstants
21 import com.android.permission.safetylabel.DataLabel as AppMetadataDataLabel
22 import com.android.permission.safetylabel.DataPurposeConstants.PURPOSE_ADVERTISING
23 import com.android.permission.safetylabel.SafetyLabel as AppMetadataSafetyLabel
24 import java.time.Instant
25 
26 /** Data class representing safety label history of installed apps. */
27 data class AppsSafetyLabelHistory(val appSafetyLabelHistories: List<AppSafetyLabelHistory>) {
28 
29     /** Data class representing the safety label history of an app. */
30     data class AppSafetyLabelHistory(
31         /** Information about the app. */
32         val appInfo: AppInfo,
33         /**
34          * A list of [SafetyLabel]s that this app has had in the past, ordered by
35          * [SafetyLabel.receivedAt].
36          *
37          * The last [SafetyLabel] in this list can be considered the last known [SafetyLabel] of the
38          * app.
39          */
40         val safetyLabelHistory: List<SafetyLabel>
41     ) {
42         init {
43             require(safetyLabelHistory.sortedBy { it.receivedAt } == safetyLabelHistory)
44             require(safetyLabelHistory.all { it.appInfo == appInfo })
45         }
46 
47         /**
48          * Returns an [AppSafetyLabelHistory] with the original history as well the provided safety
49          * label, ensuring that the maximum number of safety labels stored for this app does not
50          * exceed [maxToPersist].
51          *
52          * If the storage already has [maxToPersist] labels or more, the oldest will be discarded to
53          * make space for the newly added safety label.
54          */
55         fun withSafetyLabel(safetyLabel: SafetyLabel, maxToPersist: Int): AppSafetyLabelHistory =
56             AppSafetyLabelHistory(
57                 appInfo,
58                 safetyLabelHistory
59                     .toMutableList()
60                     .apply { add(safetyLabel) }
61                     .sortedBy { it.receivedAt }
62                     .takeLast(maxToPersist))
63     }
64 
65     /** Data class representing the information about an app. */
66     data class AppInfo(
67         val packageName: String,
68     )
69 
70     /** Data class representing an app's safety label. */
71     data class SafetyLabel(
72         /** Information about the app. */
73         val appInfo: AppInfo,
74         /** Earliest time at which the safety label was known to be accurate. */
75         val receivedAt: Instant,
76         /** Information about data use policies for an app. */
77         val dataLabel: DataLabel
78     ) {
79         /** Companion object for [SafetyLabel]. */
80         companion object {
81             /**
82              * Creates a safety label for persistence from the safety label parsed from
83              * PackageManager app metadata.
84              */
85             fun extractLocationSharingSafetyLabel(
86                 packageName: String,
87                 receivedAt: Instant,
88                 appMetadataSafetyLabel: AppMetadataSafetyLabel
89             ): SafetyLabel =
90                 SafetyLabel(
91                     AppInfo(packageName),
92                     receivedAt,
93                     DataLabel.extractLocationSharingDataLabel(appMetadataSafetyLabel.dataLabel))
94         }
95     }
96 
97     /** Data class representing an app's data use policies. */
98     data class DataLabel(
99         /** Map of category to [DataCategory] */
100         val dataShared: Map<String, DataCategory>
101     ) {
102         /** Companion object for [DataCategory]. */
103         companion object {
104             /**
105              * Creates a data label for persistence from a data label parsed from PackageManager app
106              * metadata.
107              */
108             fun extractLocationSharingDataLabel(
109                 appMetadataDataLabel: AppMetadataDataLabel
110             ): DataLabel =
111                 DataLabel(
112                     appMetadataDataLabel.dataShared
113                         .filter { it.key == DataCategoryConstants.CATEGORY_LOCATION }
114                         .mapValues { categoryEntry ->
115                             DataCategory.fromAppMetadataDataCategory(categoryEntry.value)
116                         })
117         }
118     }
119 
120     /** Data class representing an app's data use for a particular category of data. */
121     data class DataCategory(
122         /** Whether any data in this category has been used for Advertising. */
123         val containsAdvertisingPurpose: Boolean
124     ) {
125         /** Companion object for [DataCategory]. */
126         companion object {
127             /**
128              * Creates a data category for persistence from a data category parsed from
129              * PackageManager app metadata.
130              */
131             fun fromAppMetadataDataCategory(
132                 appMetadataDataCategory: AppMetadataDataCategory
133             ): DataCategory =
134                 DataCategory(
135                     appMetadataDataCategory.dataTypes.values.any {
136                         it.purposeSet.contains(PURPOSE_ADVERTISING)
137                     })
138         }
139     }
140 
141     /** Data class representing a change of an app's safety label over time. */
142     data class AppSafetyLabelDiff(
143         val safetyLabelBefore: SafetyLabel,
144         val safetyLabelAfter: SafetyLabel
145     ) {
146         init {
147             require(safetyLabelBefore.appInfo == safetyLabelAfter.appInfo)
148         }
149     }
150 }
151