1 /*
2  * Copyright (C) 2023 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 android.permissionui.cts
18 
19 import android.os.PersistableBundle
20 
21 /** Helper methods for creating test app metadata [PersistableBundle] */
22 object AppMetadata {
23     /** Returns empty App Metadata [PersistableBundle] representation */
createEmptyAppMetadatanull24     fun createEmptyAppMetadata(): PersistableBundle {
25         return PersistableBundle()
26     }
27 
28     /** Returns valid App Metadata [PersistableBundle] representation */
createDefaultAppMetadatanull29     fun createDefaultAppMetadata(): PersistableBundle {
30         val approximateLocationBundle =
31             PersistableBundle().apply { putIntArray(KEY_PURPOSES, (1..7).toList().toIntArray()) }
32 
33         val locationBundle =
34             PersistableBundle().apply {
35                 putPersistableBundle(APPROX_LOCATION, approximateLocationBundle)
36             }
37 
38         val dataSharedBundle =
39             PersistableBundle().apply { putPersistableBundle(LOCATION_CATEGORY, locationBundle) }
40 
41         val dataLabelBundle =
42             PersistableBundle().apply { putPersistableBundle(KEY_DATA_SHARED, dataSharedBundle) }
43 
44         val safetyLabelBundle =
45             PersistableBundle().apply {
46                 putLong(KEY_VERSION, INITIAL_SAFETY_LABELS_VERSION)
47                 putPersistableBundle(KEY_DATA_LABELS, dataLabelBundle)
48             }
49 
50         return PersistableBundle().apply {
51             putLong(KEY_VERSION, INITIAL_TOP_LEVEL_VERSION)
52             putPersistableBundle(KEY_SAFETY_LABELS, safetyLabelBundle)
53         }
54     }
55 
56     /**
57      * Returns invalid App Metadata [PersistableBundle] representation. Invalidity due to invalid
58      * label name usage
59      */
createInvalidAppMetadatanull60     fun createInvalidAppMetadata(): PersistableBundle {
61         val validAppMetaData = createDefaultAppMetadata()
62         val validSafetyLabel = validAppMetaData.getPersistableBundle(KEY_SAFETY_LABELS)
63 
64         return PersistableBundle().apply {
65             putLong(KEY_VERSION, INITIAL_TOP_LEVEL_VERSION)
66             putPersistableBundle(KEY_INVALID, validSafetyLabel)
67         }
68     }
69 
70     /**
71      * Returns invalid App Metadata [PersistableBundle] representation. Invalidity due to no top
72      * level meta data version number.
73      */
createInvalidAppMetadataWithoutTopLevelVersionnull74     fun createInvalidAppMetadataWithoutTopLevelVersion(): PersistableBundle {
75         val validAppMetaData = createDefaultAppMetadata()
76         val validSafetyLabel = validAppMetaData.getPersistableBundle(KEY_SAFETY_LABELS)
77 
78         return PersistableBundle().apply {
79             putPersistableBundle(KEY_SAFETY_LABELS, validSafetyLabel)
80         }
81     }
82 
83     /**
84      * Returns invalid App Metadata [PersistableBundle] representation. Invalidity due to invalid
85      * top level meta data version number.
86      */
createInvalidAppMetadataWithInvalidTopLevelVersionnull87     fun createInvalidAppMetadataWithInvalidTopLevelVersion(): PersistableBundle {
88         val validAppMetaData = createDefaultAppMetadata()
89         val validSafetyLabel = validAppMetaData.getPersistableBundle(KEY_SAFETY_LABELS)
90 
91         return PersistableBundle().apply {
92             putLong(KEY_VERSION, INVALID_TOP_LEVEL_VERSION)
93             putPersistableBundle(KEY_SAFETY_LABELS, validSafetyLabel)
94         }
95     }
96 
97     /**
98      * Returns invalid App Metadata [PersistableBundle] representation. Invalidity due to no safety
99      * label version number.
100      */
createInvalidAppMetadataWithoutSafetyLabelVersionnull101     fun createInvalidAppMetadataWithoutSafetyLabelVersion(): PersistableBundle {
102         val validAppMetaData = createDefaultAppMetadata()
103         val invalidSafetyLabel =
104             validAppMetaData.getPersistableBundle(KEY_SAFETY_LABELS).apply {
105                 this?.remove(KEY_VERSION)
106             }
107 
108         return PersistableBundle().apply {
109             putLong(KEY_VERSION, INITIAL_TOP_LEVEL_VERSION)
110             putPersistableBundle(KEY_SAFETY_LABELS, invalidSafetyLabel)
111         }
112     }
113 
114     /**
115      * Returns invalid App Metadata [PersistableBundle] representation. Invalidity due to invalid
116      * safety label version number.
117      */
createInvalidAppMetadataWithInvalidSafetyLabelVersionnull118     fun createInvalidAppMetadataWithInvalidSafetyLabelVersion(): PersistableBundle {
119         val validAppMetaData = createDefaultAppMetadata()
120         val invalidSafetyLabel =
121             validAppMetaData.getPersistableBundle(KEY_SAFETY_LABELS)?.apply {
122                 putLong(KEY_VERSION, INVALID_SAFETY_LABELS_VERSION)
123             }
124 
125         return PersistableBundle().apply {
126             putLong(KEY_VERSION, INITIAL_TOP_LEVEL_VERSION)
127             putPersistableBundle(KEY_SAFETY_LABELS, invalidSafetyLabel)
128         }
129     }
130     /** Returns an App Metadata [PersistableBundle] representation where no data is shared. */
createAppMetadataWithNoSharingnull131     fun createAppMetadataWithNoSharing(): PersistableBundle {
132         return createMetadataWithDataShared(PersistableBundle())
133     }
134 
135     /**
136      * Returns an App Metadata [PersistableBundle] representation where location data is shared, but
137      * not for advertising purpose.
138      */
createAppMetadataWithLocationSharingNoAdsnull139     fun createAppMetadataWithLocationSharingNoAds(): PersistableBundle {
140         val locationBundle =
141             PersistableBundle().apply {
142                 putPersistableBundle(
143                     APPROX_LOCATION,
144                     PersistableBundle().apply {
145                         putIntArray(
146                             KEY_PURPOSES,
147                             listOf(PURPOSE_FRAUD_PREVENTION_SECURITY).toIntArray()
148                         )
149                     }
150                 )
151             }
152 
153         val dataSharedBundle =
154             PersistableBundle().apply { putPersistableBundle(LOCATION_CATEGORY, locationBundle) }
155 
156         return createMetadataWithDataShared(dataSharedBundle)
157     }
158 
159     /**
160      * Returns an App Metadata [PersistableBundle] representation where location data is shared,
161      * including for advertising purpose.
162      */
createAppMetadataWithLocationSharingAdsnull163     fun createAppMetadataWithLocationSharingAds(): PersistableBundle {
164         val locationBundle =
165             PersistableBundle().apply {
166                 putPersistableBundle(
167                     APPROX_LOCATION,
168                     PersistableBundle().apply {
169                         putIntArray(KEY_PURPOSES, listOf(PURPOSE_ADVERTISING).toIntArray())
170                     }
171                 )
172             }
173 
174         val dataSharedBundle =
175             PersistableBundle().apply { putPersistableBundle(LOCATION_CATEGORY, locationBundle) }
176 
177         return createMetadataWithDataShared(dataSharedBundle)
178     }
179 
createMetadataWithDataSharednull180     private fun createMetadataWithDataShared(
181         dataSharedBundle: PersistableBundle
182     ): PersistableBundle {
183         val dataLabelBundle =
184             PersistableBundle().apply { putPersistableBundle(KEY_DATA_SHARED, dataSharedBundle) }
185 
186         val safetyLabelBundle =
187             PersistableBundle().apply {
188                 putLong(KEY_VERSION, INITIAL_SAFETY_LABELS_VERSION)
189                 putPersistableBundle(KEY_DATA_LABELS, dataLabelBundle)
190             }
191 
192         return PersistableBundle().apply {
193             putLong(KEY_VERSION, INITIAL_TOP_LEVEL_VERSION)
194             putPersistableBundle(KEY_SAFETY_LABELS, safetyLabelBundle)
195         }
196     }
197 
198     private const val INITIAL_SAFETY_LABELS_VERSION = 1L
199     private const val INITIAL_TOP_LEVEL_VERSION = 1L
200     private const val INVALID_SAFETY_LABELS_VERSION = -1L
201     private const val INVALID_TOP_LEVEL_VERSION = 0L
202 
203     private const val LOCATION_CATEGORY = "location"
204     private const val APPROX_LOCATION = "approx_location"
205     private const val PURPOSE_FRAUD_PREVENTION_SECURITY = 4
206     private const val PURPOSE_ADVERTISING = 5
207 
208     private const val KEY_VERSION = "version"
209     private const val KEY_SAFETY_LABELS = "safety_labels"
210     private const val KEY_INVALID = "invalid_safety_labels"
211     private const val KEY_DATA_SHARED = "data_shared"
212     private const val KEY_DATA_LABELS = "data_labels"
213     private const val KEY_PURPOSES = "purposes"
214 }
215