1 /*
2  * 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.permission.safetylabel;
18 
19 import static java.lang.annotation.RetentionPolicy.SOURCE;
20 
21 import android.annotation.StringDef;
22 import android.util.ArrayMap;
23 
24 import java.lang.annotation.Retention;
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.HashSet;
28 import java.util.Map;
29 import java.util.Set;
30 
31 /**
32  * Constants and util methods for determining valid {@link String} data categories for usage within
33  * {@link SafetyLabel}, {@link DataCategory}, and {@link DataType}
34  */
35 public class DataTypeConstants {
36 
37     /**
38      * List of valid Safety Label data collection/sharing types for {@link
39      * DataCategoryConstants#CATEGORY_PERSONAL}
40      */
41     @Retention(SOURCE)
42     @StringDef(
43             prefix = "PERSONAL_",
44             value = {
45                 PERSONAL_NAME,
46                 PERSONAL_EMAIL_ADDRESS,
47                 PERSONAL_PHYSICAL_ADDRESS,
48                 PERSONAL_PHONE_NUMBER,
49                 PERSONAL_RACE_ETHNICITY,
50                 PERSONAL_POLITICAL_OR_RELIGIOUS_BELIEFS,
51                 PERSONAL_SEXUAL_ORIENTATION_OR_GENDER_IDENTITY,
52                 PERSONAL_IDENTIFIERS,
53                 PERSONAL_OTHER,
54             })
55     public @interface PersonalType {}
56 
57     public static final String PERSONAL_NAME = "name";
58     public static final String PERSONAL_EMAIL_ADDRESS = "email_address";
59     public static final String PERSONAL_PHYSICAL_ADDRESS = "physical_address";
60     public static final String PERSONAL_PHONE_NUMBER = "phone_number";
61     public static final String PERSONAL_RACE_ETHNICITY = "race_ethnicity";
62     public static final String PERSONAL_POLITICAL_OR_RELIGIOUS_BELIEFS =
63             "political_or_religious_beliefs";
64     public static final String PERSONAL_SEXUAL_ORIENTATION_OR_GENDER_IDENTITY =
65             "sexual_orientation_or_gender_identity";
66     public static final String PERSONAL_IDENTIFIERS = "personal_identifiers";
67     public static final String PERSONAL_OTHER = "other";
68 
69     @PersonalType
70     private static final Set<String> VALID_TYPES_PERSONAL =
71             Collections.unmodifiableSet(
72                     new HashSet<>(
73                             Arrays.asList(
74                                     PERSONAL_NAME,
75                                     PERSONAL_EMAIL_ADDRESS,
76                                     PERSONAL_PHYSICAL_ADDRESS,
77                                     PERSONAL_PHONE_NUMBER,
78                                     PERSONAL_RACE_ETHNICITY,
79                                     PERSONAL_POLITICAL_OR_RELIGIOUS_BELIEFS,
80                                     PERSONAL_SEXUAL_ORIENTATION_OR_GENDER_IDENTITY,
81                                     PERSONAL_IDENTIFIERS,
82                                     PERSONAL_OTHER)));
83 
84     /**
85      * List of valid Safety Label data collection/sharing types for {@link
86      * DataCategoryConstants#CATEGORY_FINANCIAL}
87      */
88     @Retention(SOURCE)
89     @StringDef(
90             prefix = "FINANCIAL_",
91             value = {
92                 FINANCIAL_CARD_BANK_ACCOUNT,
93                 FINANCIAL_PURCHASE_HISTORY,
94                 FINANCIAL_CREDIT_SCORE,
95                 FINANCIAL_OTHER,
96             })
97     public @interface FinancialType {}
98 
99     public static final String FINANCIAL_CARD_BANK_ACCOUNT = "card_bank_account";
100     public static final String FINANCIAL_PURCHASE_HISTORY = "purchase_history";
101     public static final String FINANCIAL_CREDIT_SCORE = "credit_score";
102     public static final String FINANCIAL_OTHER = "other";
103 
104     @FinancialType
105     private static final Set<String> VALID_TYPES_FINANCIAL =
106             Collections.unmodifiableSet(
107                     new HashSet<>(
108                             Arrays.asList(
109                                     FINANCIAL_CARD_BANK_ACCOUNT,
110                                     FINANCIAL_PURCHASE_HISTORY,
111                                     FINANCIAL_CREDIT_SCORE,
112                                     FINANCIAL_OTHER)));
113 
114     /**
115      * List of valid Safety Label data collection/sharing types for {@link
116      * DataCategoryConstants#CATEGORY_LOCATION}
117      */
118     @Retention(SOURCE)
119     @StringDef(
120             prefix = "LOCATION_",
121             value = {
122                 LOCATION_APPROX_LOCATION,
123                 LOCATION_PRECISE_LOCATION,
124             })
125     public @interface LocationType {}
126 
127     public static final String LOCATION_APPROX_LOCATION = "approx_location";
128     public static final String LOCATION_PRECISE_LOCATION = "precise_location";
129 
130     @LocationType
131     private static final Set<String> VALID_TYPES_LOCATION =
132             Collections.unmodifiableSet(
133                     new HashSet<>(
134                             Arrays.asList(LOCATION_APPROX_LOCATION, LOCATION_PRECISE_LOCATION)));
135 
136     /**
137      * List of valid Safety Label data collection/sharing types for {@link
138      * DataCategoryConstants#CATEGORY_EMAIL_TEXT_MESSAGE}
139      */
140     @Retention(SOURCE)
141     @StringDef(
142             prefix = "EMAIL_TEXT_MESSAGE_",
143             value = {
144                 EMAIL_TEXT_MESSAGE_EMAILS,
145                 EMAIL_TEXT_MESSAGE_TEXT_MESSAGES,
146                 EMAIL_TEXT_MESSAGE_OTHER,
147             })
148     public @interface EmailTextMessageType {}
149 
150     public static final String EMAIL_TEXT_MESSAGE_EMAILS = "emails";
151     public static final String EMAIL_TEXT_MESSAGE_TEXT_MESSAGES = "text_messages";
152     public static final String EMAIL_TEXT_MESSAGE_OTHER = "other";
153 
154     @EmailTextMessageType
155     private static final Set<String> VALID_TYPES_EMAIL_TEXT_MESSAGE =
156             Collections.unmodifiableSet(
157                     new HashSet<>(
158                             Arrays.asList(
159                                     EMAIL_TEXT_MESSAGE_EMAILS,
160                                     EMAIL_TEXT_MESSAGE_TEXT_MESSAGES,
161                                     EMAIL_TEXT_MESSAGE_OTHER)));
162 
163     /**
164      * List of valid Safety Label data collection/sharing types for {@link
165      * DataCategoryConstants#CATEGORY_PHOTO_VIDEO}
166      */
167     @Retention(SOURCE)
168     @StringDef(
169             prefix = "PHOTO_VIDEO_",
170             value = {
171                 PHOTO_VIDEO_PHOTOS,
172                 PHOTO_VIDEO_VIDEOS,
173             })
174     public @interface PhotoVideoType {}
175 
176     public static final String PHOTO_VIDEO_PHOTOS = "photos";
177     public static final String PHOTO_VIDEO_VIDEOS = "videos";
178 
179     @PhotoVideoType
180     private static final Set<String> VALID_TYPES_PHOTO_VIDEO =
181             Collections.unmodifiableSet(
182                     new HashSet<>(Arrays.asList(PHOTO_VIDEO_PHOTOS, PHOTO_VIDEO_VIDEOS)));
183 
184     /**
185      * List of valid Safety Label data collection/sharing types for {@link
186      * DataCategoryConstants#CATEGORY_AUDIO}
187      */
188     @Retention(SOURCE)
189     @StringDef(
190             prefix = "AUDIO_",
191             value = {AUDIO_SOUND_RECORDINGS, AUDIO_MUSIC_FILES, AUDIO_OTHER})
192     public @interface AudioType {}
193 
194     public static final String AUDIO_SOUND_RECORDINGS = "sound_recordings";
195     public static final String AUDIO_MUSIC_FILES = "music_files";
196     public static final String AUDIO_OTHER = "other";
197 
198     @AudioType
199     private static final Set<String> VALID_TYPES_AUDIO =
200             Collections.unmodifiableSet(
201                     new HashSet<>(
202                             Arrays.asList(AUDIO_SOUND_RECORDINGS, AUDIO_MUSIC_FILES, AUDIO_OTHER)));
203 
204     /**
205      * List of valid Safety Label data collection/sharing types for {@link
206      * DataCategoryConstants#CATEGORY_STORAGE}
207      */
208     @Retention(SOURCE)
209     @StringDef(
210             prefix = "STORAGE_",
211             value = {
212                 STORAGE_FILES_DOCS,
213             })
214     public @interface StorageType {}
215 
216     public static final String STORAGE_FILES_DOCS = "files_docs";
217 
218     @StorageType
219     private static final Set<String> VALID_TYPES_STORAGE =
220             Collections.unmodifiableSet(new HashSet<>(Arrays.asList(STORAGE_FILES_DOCS)));
221 
222     /**
223      * List of valid Safety Label data collection/sharing types for {@link
224      * DataCategoryConstants#CATEGORY_HEALTH_FITNESS}
225      */
226     @Retention(SOURCE)
227     @StringDef(
228             prefix = "HEALTH_FITNESS_",
229             value = {
230                 HEALTH_FITNESS_HEALTH,
231                 HEALTH_FITNESS_FITNESS,
232             })
233     public @interface HealthFitnessType {}
234 
235     public static final String HEALTH_FITNESS_HEALTH = "health";
236     public static final String HEALTH_FITNESS_FITNESS = "fitness";
237 
238     @HealthFitnessType
239     private static final Set<String> VALID_TYPES_HEALTH_FITNESS =
240             Collections.unmodifiableSet(
241                     new HashSet<>(Arrays.asList(HEALTH_FITNESS_HEALTH, HEALTH_FITNESS_FITNESS)));
242 
243     /**
244      * List of valid Safety Label data collection/sharing types for {@link
245      * DataCategoryConstants#CATEGORY_CONTACTS}
246      */
247     @Retention(SOURCE)
248     @StringDef(
249             prefix = "CONTACTS_",
250             value = {
251                 CONTACTS_CONTACTS,
252             })
253     public @interface ContactsType {}
254 
255     public static final String CONTACTS_CONTACTS = "contacts";
256 
257     @ContactsType
258     private static final Set<String> VALID_TYPES_CONTACTS =
259             Collections.unmodifiableSet(new HashSet<>(Arrays.asList(CONTACTS_CONTACTS)));
260 
261     /**
262      * List of valid Safety Label data collection/sharing types for {@link
263      * DataCategoryConstants#CATEGORY_CALENDAR}
264      */
265     @Retention(SOURCE)
266     @StringDef(
267             prefix = "CALENDAR_",
268             value = {
269                 CALENDAR_CALENDAR,
270             })
271     public @interface CalendarType {}
272 
273     public static final String CALENDAR_CALENDAR = "calendar";
274 
275     @CalendarType
276     private static final Set<String> VALID_TYPES_CALENDAR =
277             Collections.unmodifiableSet(new HashSet<>(Arrays.asList(CALENDAR_CALENDAR)));
278 
279     /**
280      * List of valid Safety Label data collection/sharing types for {@link
281      * DataCategoryConstants#CATEGORY_IDENTIFIERS}
282      */
283     @Retention(SOURCE)
284     @StringDef(
285             prefix = "IDENTIFIERS_",
286             value = {
287                 IDENTIFIERS_OTHER,
288             })
289     public @interface IdentifiersType {}
290 
291     public static final String IDENTIFIERS_OTHER = "other";
292 
293     @IdentifiersType
294     private static final Set<String> VALID_TYPES_IDENTIFIERS =
295             Collections.unmodifiableSet(new HashSet<>(Arrays.asList(IDENTIFIERS_OTHER)));
296 
297     /**
298      * List of valid Safety Label data collection/sharing types for {@link
299      * DataCategoryConstants#CATEGORY_APP_PERFORMANCE}
300      */
301     @Retention(SOURCE)
302     @StringDef(
303             prefix = "APP_PERFORMANCE_",
304             value = {
305                 APP_PERFORMANCE_CRASH_LOGS,
306                 APP_PERFORMANCE_PERFORMANCE_DIAGNOSTICS,
307                 APP_PERFORMANCE_OTHER,
308             })
309     public @interface AppPerformanceType {}
310 
311     public static final String APP_PERFORMANCE_CRASH_LOGS = "crash_logs";
312     public static final String APP_PERFORMANCE_PERFORMANCE_DIAGNOSTICS = "performance_diagnostics";
313     public static final String APP_PERFORMANCE_OTHER = "other";
314 
315     @AppPerformanceType
316     private static final Set<String> VALID_TYPES_APP_PERFORMANCE =
317             Collections.unmodifiableSet(
318                     new HashSet<>(
319                             Arrays.asList(
320                                     APP_PERFORMANCE_CRASH_LOGS,
321                                     APP_PERFORMANCE_PERFORMANCE_DIAGNOSTICS,
322                                     APP_PERFORMANCE_OTHER)));
323 
324     /**
325      * List of valid Safety Label data collection/sharing types for {@link
326      * DataCategoryConstants#CATEGORY_ACTIONS_IN_APP}
327      */
328     @Retention(SOURCE)
329     @StringDef(
330             prefix = "ACTIONS_IN_APP_",
331             value = {
332                 ACTIONS_IN_APP_USER_INTERACTION,
333                 ACTIONS_IN_APP_IN_APP_SEARCH_HISTORY,
334                 ACTIONS_IN_APP_INSTALLED_APPS,
335                 ACTIONS_IN_APP_USER_GENERATED_CONTENT,
336                 ACTIONS_IN_APP_OTHER,
337             })
338     public @interface ActionsInAppType {}
339 
340     public static final String ACTIONS_IN_APP_USER_INTERACTION = "user_interaction";
341     public static final String ACTIONS_IN_APP_IN_APP_SEARCH_HISTORY = "in_app_search_history";
342     public static final String ACTIONS_IN_APP_INSTALLED_APPS = "installed_apps";
343     public static final String ACTIONS_IN_APP_USER_GENERATED_CONTENT = "user_generated_content";
344     public static final String ACTIONS_IN_APP_OTHER = "other";
345 
346     @ActionsInAppType
347     private static final Set<String> VALID_TYPES_ACTIONS_IN_APP =
348             Collections.unmodifiableSet(
349                     new HashSet<>(
350                             Arrays.asList(
351                                     ACTIONS_IN_APP_USER_INTERACTION,
352                                     ACTIONS_IN_APP_IN_APP_SEARCH_HISTORY,
353                                     ACTIONS_IN_APP_INSTALLED_APPS,
354                                     ACTIONS_IN_APP_USER_GENERATED_CONTENT,
355                                     ACTIONS_IN_APP_OTHER)));
356 
357     /**
358      * List of valid Safety Label data collection/sharing types for {@link
359      * DataCategoryConstants#CATEGORY_SEARCH_AND_BROWSING}
360      */
361     @Retention(SOURCE)
362     @StringDef(
363             prefix = "SEARCH_AND_BROWSING_",
364             value = {
365                 SEARCH_AND_BROWSING_WEB_BROWSING_HISTORY,
366             })
367     public @interface SearchAndBrowsingType {}
368 
369     public static final String SEARCH_AND_BROWSING_WEB_BROWSING_HISTORY = "web_browsing_history";
370 
371     @SearchAndBrowsingType
372     private static final Set<String> VALID_TYPES_SEARCH_AND_BROWSING =
373             Collections.unmodifiableSet(
374                     new HashSet<>(Arrays.asList(SEARCH_AND_BROWSING_WEB_BROWSING_HISTORY)));
375 
376     private static final Map<String, Set<String>> VALID_TYPES_FOR_CATEGORY_MAP;
377 
378     /** Returns {@link Set} of valid types for the specified {@link String} category key */
getValidDataTypesForCategory( @ataCategoryConstants.Category String category)379     public static Set<String> getValidDataTypesForCategory(
380             @DataCategoryConstants.Category String category) {
381         return VALID_TYPES_FOR_CATEGORY_MAP.containsKey(category)
382                 ? VALID_TYPES_FOR_CATEGORY_MAP.get(category)
383                 : Collections.emptySet();
384     }
385 
386     static {
387         VALID_TYPES_FOR_CATEGORY_MAP = new ArrayMap<>();
VALID_TYPES_FOR_CATEGORY_MAP.put( DataCategoryConstants.CATEGORY_PERSONAL, VALID_TYPES_PERSONAL)388         VALID_TYPES_FOR_CATEGORY_MAP.put(
389                 DataCategoryConstants.CATEGORY_PERSONAL, VALID_TYPES_PERSONAL);
VALID_TYPES_FOR_CATEGORY_MAP.put( DataCategoryConstants.CATEGORY_FINANCIAL, VALID_TYPES_FINANCIAL)390         VALID_TYPES_FOR_CATEGORY_MAP.put(
391                 DataCategoryConstants.CATEGORY_FINANCIAL, VALID_TYPES_FINANCIAL);
VALID_TYPES_FOR_CATEGORY_MAP.put( DataCategoryConstants.CATEGORY_LOCATION, VALID_TYPES_LOCATION)392         VALID_TYPES_FOR_CATEGORY_MAP.put(
393                 DataCategoryConstants.CATEGORY_LOCATION, VALID_TYPES_LOCATION);
VALID_TYPES_FOR_CATEGORY_MAP.put( DataCategoryConstants.CATEGORY_EMAIL_TEXT_MESSAGE, VALID_TYPES_EMAIL_TEXT_MESSAGE)394         VALID_TYPES_FOR_CATEGORY_MAP.put(
395                 DataCategoryConstants.CATEGORY_EMAIL_TEXT_MESSAGE, VALID_TYPES_EMAIL_TEXT_MESSAGE);
VALID_TYPES_FOR_CATEGORY_MAP.put( DataCategoryConstants.CATEGORY_PHOTO_VIDEO, VALID_TYPES_PHOTO_VIDEO)396         VALID_TYPES_FOR_CATEGORY_MAP.put(
397                 DataCategoryConstants.CATEGORY_PHOTO_VIDEO, VALID_TYPES_PHOTO_VIDEO);
VALID_TYPES_FOR_CATEGORY_MAP.put(DataCategoryConstants.CATEGORY_AUDIO, VALID_TYPES_AUDIO)398         VALID_TYPES_FOR_CATEGORY_MAP.put(DataCategoryConstants.CATEGORY_AUDIO, VALID_TYPES_AUDIO);
VALID_TYPES_FOR_CATEGORY_MAP.put( DataCategoryConstants.CATEGORY_STORAGE, VALID_TYPES_STORAGE)399         VALID_TYPES_FOR_CATEGORY_MAP.put(
400                 DataCategoryConstants.CATEGORY_STORAGE, VALID_TYPES_STORAGE);
VALID_TYPES_FOR_CATEGORY_MAP.put( DataCategoryConstants.CATEGORY_HEALTH_FITNESS, VALID_TYPES_HEALTH_FITNESS)401         VALID_TYPES_FOR_CATEGORY_MAP.put(
402                 DataCategoryConstants.CATEGORY_HEALTH_FITNESS, VALID_TYPES_HEALTH_FITNESS);
VALID_TYPES_FOR_CATEGORY_MAP.put( DataCategoryConstants.CATEGORY_CONTACTS, VALID_TYPES_CONTACTS)403         VALID_TYPES_FOR_CATEGORY_MAP.put(
404                 DataCategoryConstants.CATEGORY_CONTACTS, VALID_TYPES_CONTACTS);
VALID_TYPES_FOR_CATEGORY_MAP.put( DataCategoryConstants.CATEGORY_CALENDAR, VALID_TYPES_CALENDAR)405         VALID_TYPES_FOR_CATEGORY_MAP.put(
406                 DataCategoryConstants.CATEGORY_CALENDAR, VALID_TYPES_CALENDAR);
VALID_TYPES_FOR_CATEGORY_MAP.put( DataCategoryConstants.CATEGORY_IDENTIFIERS, VALID_TYPES_IDENTIFIERS)407         VALID_TYPES_FOR_CATEGORY_MAP.put(
408                 DataCategoryConstants.CATEGORY_IDENTIFIERS, VALID_TYPES_IDENTIFIERS);
VALID_TYPES_FOR_CATEGORY_MAP.put( DataCategoryConstants.CATEGORY_APP_PERFORMANCE, VALID_TYPES_APP_PERFORMANCE)409         VALID_TYPES_FOR_CATEGORY_MAP.put(
410                 DataCategoryConstants.CATEGORY_APP_PERFORMANCE, VALID_TYPES_APP_PERFORMANCE);
VALID_TYPES_FOR_CATEGORY_MAP.put( DataCategoryConstants.CATEGORY_ACTIONS_IN_APP, VALID_TYPES_ACTIONS_IN_APP)411         VALID_TYPES_FOR_CATEGORY_MAP.put(
412                 DataCategoryConstants.CATEGORY_ACTIONS_IN_APP, VALID_TYPES_ACTIONS_IN_APP);
VALID_TYPES_FOR_CATEGORY_MAP.put( DataCategoryConstants.CATEGORY_SEARCH_AND_BROWSING, VALID_TYPES_SEARCH_AND_BROWSING)413         VALID_TYPES_FOR_CATEGORY_MAP.put(
414                 DataCategoryConstants.CATEGORY_SEARCH_AND_BROWSING,
415                 VALID_TYPES_SEARCH_AND_BROWSING);
416     }
417 
DataTypeConstants()418     private DataTypeConstants() {
419         /* do nothing - hide constructor */
420     }
421 }
422