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.safetycenter.testing
18 
19 import android.content.Context
20 import android.content.pm.PackageManager.GET_SIGNING_CERTIFICATES
21 import android.content.pm.PackageManager.PackageInfoFlags
22 import android.content.res.Resources
23 import android.os.Build
24 import android.os.Build.VERSION_CODES.TIRAMISU
25 import android.safetycenter.SafetySourceData
26 import android.safetycenter.config.SafetyCenterConfig
27 import android.safetycenter.config.SafetySource
28 import android.safetycenter.config.SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC
29 import android.safetycenter.config.SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY
30 import android.safetycenter.config.SafetySource.SAFETY_SOURCE_TYPE_STATIC
31 import android.safetycenter.config.SafetySourcesGroup
32 import androidx.annotation.RequiresApi
33 import com.android.modules.utils.build.SdkLevel
34 import com.android.permission.flags.Flags
35 import com.android.safetycenter.testing.SettingsPackage.getSettingsPackageName
36 import java.security.MessageDigest
37 
38 /**
39  * A class that provides [SafetyCenterConfig] objects and associated constants to facilitate setting
40  * up safety sources for testing.
41  */
42 @RequiresApi(TIRAMISU)
43 class SafetyCenterTestConfigs(private val context: Context) {
44     /** The certificate hash signing the current package. */
45     val packageCertHash =
46         MessageDigest.getInstance("SHA256")
47             .digest(
48                 context.packageManager
49                     .getPackageInfo(
50                         context.packageName,
51                         PackageInfoFlags.of(GET_SIGNING_CERTIFICATES.toLong()),
52                     )
53                     .signingInfo!!
54                     .apkContentsSigners[0]
55                     .toByteArray()
56             )
<lambda>null57             .joinToString("") { "%02x".format(it) }
58 
59     /** A simple [SafetyCenterConfig] for tests with a single source of id [SINGLE_SOURCE_ID]. */
60     val singleSourceConfig = singleSourceConfig(dynamicSafetySource(SINGLE_SOURCE_ID))
61 
62     /**
63      * A simple [SafetyCenterConfig] with an invalid intent action for tests with a single source of
64      * id [SINGLE_SOURCE_ID].
65      */
66     val singleSourceInvalidIntentConfig =
67         singleSourceConfig(
68             dynamicSafetySourceBuilder(SINGLE_SOURCE_ID)
69                 .setIntentAction(INTENT_ACTION_NOT_RESOLVING)
70                 .build()
71         )
72 
73     /**
74      * Same as [singleSourceConfig] but with an `intentAction` that will resolve implicitly; i.e.
75      * the source's `packageName` does not own the activity resolved by the `intentAction`.
76      */
77     val implicitIntentSingleSourceConfig =
78         singleSourceConfig(
79             dynamicSafetySourceBuilder(SINGLE_SOURCE_ID)
80                 // A valid package name that is *not* CTS.
81                 .setPackageName(context.packageManager.permissionControllerPackageName)
82                 // Exported activity that lives in the CTS package. The PC package does
83                 // implement this intent action so the activity has to resolve
84                 // implicitly.
85                 .setIntentAction(ACTION_TEST_ACTIVITY_EXPORTED)
86                 .build()
87         )
88 
89     /** A simple [SafetyCenterConfig] for tests with a source max severity level of 0. */
90     val severityZeroConfig =
91         singleSourceConfig(
92             dynamicSafetySourceBuilder(SINGLE_SOURCE_ID).setMaxSeverityLevel(0).build()
93         )
94 
95     /** A simple [SafetyCenterConfig] for tests with a fake/incorrect package cert hash. */
96     val singleSourceWithFakeCert: SafetyCenterConfig
97         @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
98         get() =
99             singleSourceConfig(
100                 dynamicSafetySourceBuilder(SINGLE_SOURCE_ID)
101                     .addPackageCertificateHash(PACKAGE_CERT_HASH_FAKE)
102                     .build()
103             )
104 
105     /**
106      * A simple [SafetyCenterConfig] for tests with a invalid package cert hash (not a hex-formatted
107      * byte string).
108      */
109     val singleSourceWithInvalidCert: SafetyCenterConfig
110         @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
111         get() =
112             singleSourceConfig(
113                 dynamicSafetySourceBuilder(SINGLE_SOURCE_ID)
114                     .addPackageCertificateHash(PACKAGE_CERT_HASH_INVALID)
115                     .build()
116             )
117 
118     /**
119      * A simple [SafetyCenterConfig] for tests with a source that does not support refresh on page
120      * open.
121      */
122     val noPageOpenConfig =
123         singleSourceConfig(
124             dynamicSafetySourceBuilder(SINGLE_SOURCE_ID).setRefreshOnPageOpenAllowed(false).build()
125         )
126 
127     /** A Simple [SafetyCenterConfig] with an issue only source. */
128     val issueOnlySourceConfig =
129         singleSourceConfig(issueOnlySafetySourceBuilder(ISSUE_ONLY_ALL_OPTIONAL_ID).build())
130 
131     /** A Simple [SafetyCenterConfig] with an issue only source supporting all profiles. */
132     val issueOnlySourceAllProfileConfig =
133         singleSourceConfig(
134             issueOnlyAllProfileSafetySourceBuilder(ISSUE_ONLY_ALL_PROFILE_SOURCE_ID).build()
135         )
136 
137     /**
138      * A Simple [SafetyCenterConfig] with an issue only source inside a [SafetySourcesGroup] with
139      * null title.
140      */
141     val issueOnlySourceNoGroupTitleConfig =
142         SafetyCenterConfig.Builder()
143             .addSafetySourcesGroup(
144                 safetySourcesGroupBuilder(SINGLE_SOURCE_GROUP_ID)
145                     .setTitleResId(Resources.ID_NULL)
146                     .addSafetySource(
147                         issueOnlySafetySourceBuilder(ISSUE_ONLY_ALL_OPTIONAL_ID).build()
148                     )
149                     .build()
150             )
151             .build()
152 
153     /** A dynamic source with [OTHER_PACKAGE_NAME] */
154     val dynamicOtherPackageSafetySource =
155         dynamicSafetySourceBuilder(DYNAMIC_OTHER_PACKAGE_ID)
156             .setRefreshOnPageOpenAllowed(false)
157             .setPackageName(OTHER_PACKAGE_NAME)
158             .build()
159 
160     /** A [SafetyCenterConfig] with a dynamic source in a different, missing package. */
161     val singleSourceOtherPackageConfig = singleSourceConfig(dynamicOtherPackageSafetySource)
162 
163     /** A [SafetyCenterConfig] with a dynamic hidden-by-default source. */
164     val hiddenSourceConfig =
165         singleSourceConfig(
166             dynamicSafetySourceBuilder(DYNAMIC_HIDDEN_ID)
167                 .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
168                 .build()
169         )
170 
171     /** A simple [SafetyCenterConfig] with a source supporting all profiles. */
172     val singleSourceAllProfileConfig =
173         singleSourceConfig(
174             dynamicAllProfileSafetySourceBuilder(SINGLE_SOURCE_ALL_PROFILE_ID).build()
175         )
176 
177     /** A simple [SafetyCenterConfig] for tests with multiple sources. */
178     val multipleSourcesConfig =
179         SafetyCenterConfig.Builder()
180             .addSafetySourcesGroup(
181                 safetySourcesGroupBuilder(MULTIPLE_SOURCES_GROUP_ID_1)
182                     .addSafetySource(dynamicSafetySource(SOURCE_ID_1))
183                     .addSafetySource(dynamicSafetySource(SOURCE_ID_2))
184                     .build()
185             )
186             .addSafetySourcesGroup(
187                 safetySourcesGroupBuilder(MULTIPLE_SOURCES_GROUP_ID_2)
188                     .setTitleResId(android.R.string.copy)
189                     .setSummaryResId(android.R.string.cancel)
190                     .addSafetySource(
191                         dynamicSafetySourceBuilder(SOURCE_ID_3)
192                             .setTitleResId(android.R.string.copy)
193                             .setSummaryResId(android.R.string.cancel)
194                             .setRefreshOnPageOpenAllowed(false)
195                             .build()
196                     )
197                     .build()
198             )
199             .build()
200 
201     /** A simple [SafetyCenterConfig] with multiple sources in a single [SafetySourcesGroup]. */
202     val multipleSourcesInSingleGroupConfig =
203         SafetyCenterConfig.Builder()
204             .addSafetySourcesGroup(
205                 safetySourcesGroupBuilder(MULTIPLE_SOURCES_GROUP_ID_1)
206                     .addSafetySource(dynamicSafetySource(SOURCE_ID_1))
207                     .addSafetySource(dynamicSafetySource(SOURCE_ID_2))
208                     .addSafetySource(dynamicSafetySource(SOURCE_ID_3))
209                     .build()
210             )
211             .build()
212 
213     /** A simple [SafetyCenterConfig] for tests with multiple sources with deduplication info. */
214     val multipleSourcesWithDeduplicationInfoConfig: SafetyCenterConfig
215         @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
216         get() =
217             SafetyCenterConfig.Builder()
218                 .addSafetySourcesGroup(
219                     safetySourcesGroupBuilder(MULTIPLE_SOURCES_GROUP_ID_1)
220                         .addSafetySource(
221                             issueOnlySafetySourceWithDuplicationInfo(
222                                 SOURCE_ID_1,
223                                 DEDUPLICATION_GROUP_1,
224                             )
225                         )
226                         .addSafetySource(
227                             issueOnlySafetySourceWithDuplicationInfo(
228                                 SOURCE_ID_2,
229                                 DEDUPLICATION_GROUP_1,
230                             )
231                         )
232                         .addSafetySource(
233                             issueOnlySafetySourceWithDuplicationInfo(
234                                 SOURCE_ID_3,
235                                 DEDUPLICATION_GROUP_2,
236                             )
237                         )
238                         .addSafetySource(
239                             issueOnlySafetySourceWithDuplicationInfo(
240                                 SOURCE_ID_4,
241                                 DEDUPLICATION_GROUP_3,
242                             )
243                         )
244                         .build()
245                 )
246                 .addSafetySourcesGroup(
247                     safetySourcesGroupBuilder(MULTIPLE_SOURCES_GROUP_ID_2)
248                         .addSafetySource(
249                             issueOnlySafetySourceWithDuplicationInfo(
250                                 SOURCE_ID_5,
251                                 DEDUPLICATION_GROUP_1,
252                             )
253                         )
254                         .addSafetySource(
255                             issueOnlySafetySourceWithDuplicationInfo(
256                                 SOURCE_ID_6,
257                                 DEDUPLICATION_GROUP_3,
258                             )
259                         )
260                         .build()
261                 )
262                 .addSafetySourcesGroup(
263                     safetySourcesGroupBuilder(MULTIPLE_SOURCES_GROUP_ID_3)
264                         .addSafetySource(
265                             issueOnlySafetySourceWithDuplicationInfo(
266                                 SOURCE_ID_7,
267                                 DEDUPLICATION_GROUP_3,
268                             )
269                         )
270                         .build()
271                 )
272                 .build()
273 
274     /**
275      * A simple [SafetyCenterConfig] for testing the Privacy subpage. Note that this config contains
276      * the [PRIVACY_SOURCE_ID_1] source that is part of the generic category, and the [SOURCE_ID_1]
277      * that is part of the data category.
278      */
279     val privacySubpageConfig: SafetyCenterConfig
280         @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
281         get() =
282             SafetyCenterConfig.Builder()
283                 .addSafetySourcesGroup(
284                     safetySourcesGroupBuilder(ANDROID_PRIVACY_SOURCES_GROUP_ID)
285                         .addSafetySource(dynamicSafetySource(PRIVACY_SOURCE_ID_1))
286                         .addSafetySource(dynamicSafetySource(SOURCE_ID_1))
287                         .build()
288                 )
289                 .build()
290 
291     /**
292      * A simple [SafetyCenterConfig] without data sources for testing the Privacy subpage. Note that
293      * this config contains only [PRIVACY_SOURCE_ID_1] source that is part of the generic category.
294      * Hence it doesn't have any data category sources.
295      */
296     val privacySubpageWithoutDataSourcesConfig: SafetyCenterConfig
297         @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
298         get() =
299             SafetyCenterConfig.Builder()
300                 .addSafetySourcesGroup(
301                     safetySourcesGroupBuilder(ANDROID_PRIVACY_SOURCES_GROUP_ID)
302                         .addSafetySource(dynamicSafetySource(PRIVACY_SOURCE_ID_1))
303                         .build()
304                 )
305                 .build()
306 
307     /** Source included in [dynamicSourceGroup1]. */
308     val dynamicSource1 = dynamicSafetySource(SOURCE_ID_1)
309 
310     /** Source included in [dynamicSourceGroup1]. */
311     val dynamicSource2 = dynamicSafetySource(SOURCE_ID_2)
312 
313     /** Source included in [dynamicSourceGroup2]. */
314     val dynamicSource3 = dynamicSafetySource(SOURCE_ID_3)
315 
316     private val dynamicSource4 = dynamicSafetySource(SOURCE_ID_4)
317     private val dynamicSource5 = dynamicSafetySource(SOURCE_ID_5)
318 
319     /** Source group provided by [multipleSourceGroupsConfig]. */
320     val dynamicSourceGroup1 =
321         safetySourcesGroupBuilder(MULTIPLE_SOURCES_GROUP_ID_1)
322             .addSafetySource(dynamicSource1)
323             .addSafetySource(dynamicSource2)
324             .setTitleResId(android.R.string.copy)
325             .setSummaryResId(android.R.string.cut)
326             .build()
327 
328     /** Source group provided by [multipleSourceGroupsConfig]. */
329     val dynamicSourceGroup2 =
330         safetySourcesGroupBuilder(MULTIPLE_SOURCES_GROUP_ID_2)
331             .addSafetySource(dynamicSource3)
332             .setTitleResId(android.R.string.paste)
333             .setSummaryResId(android.R.string.cancel)
334             .build()
335 
336     /** Source group provided by [multipleSourceGroupsConfig]. */
337     val dynamicSourceGroup3 =
338         safetySourcesGroupBuilder(MULTIPLE_SOURCES_GROUP_ID_3)
339             .addSafetySource(dynamicSource4)
340             .addSafetySource(dynamicSource5)
341             .setTitleResId(android.R.string.dialog_alert_title)
342             .setSummaryResId(android.R.string.selectAll)
343             .build()
344 
345     /** A simple [SafetyCenterConfig] for tests with multiple groups of multiple sources. */
346     val multipleSourceGroupsConfig =
347         SafetyCenterConfig.Builder()
348             .addSafetySourcesGroup(dynamicSourceGroup1)
349             .addSafetySourcesGroup(dynamicSourceGroup2)
350             .addSafetySourcesGroup(dynamicSourceGroup3)
351             .build()
352 
353     /**
354      * A simple [SafetyCenterConfig] for tests with a single stateful group containing 2 dynamic
355      * sources and an issue only source.
356      */
357     val entryGroupWithIssueOnlyConfig =
358         SafetyCenterConfig.Builder()
359             .addSafetySourcesGroup(
360                 safetySourcesGroupBuilder("EntryGroupWithIssueOnly")
361                     .addSafetySource(dynamicSource1)
362                     .addSafetySource(dynamicSource2)
363                     .addSafetySource(
364                         issueOnlySafetySourceBuilder(ISSUE_ONLY_ALL_OPTIONAL_ID).build()
365                     )
366                     .build()
367             )
368             .build()
369 
370     /**
371      * A simple [SafetyCenterConfig] for tests with multiple sources with one source having an
372      * invalid default intent.
373      */
374     val multipleSourcesConfigWithSourceWithInvalidIntent =
375         SafetyCenterConfig.Builder()
376             .addSafetySourcesGroup(
377                 safetySourcesGroupBuilder(MULTIPLE_SOURCES_GROUP_ID_1)
378                     .addSafetySource(
379                         dynamicSafetySourceBuilder(SOURCE_ID_1)
380                             .setIntentAction(INTENT_ACTION_NOT_RESOLVING)
381                             .build()
382                     )
383                     .addSafetySource(dynamicSafetySource(SOURCE_ID_2))
384                     .build()
385             )
386             .build()
387 
388     /** Source provided by [staticSourcesConfig]. */
389     val staticSource1 =
390         staticSafetySourceBuilder("test_static_source_id_1")
391             .setTitleResId(android.R.string.dialog_alert_title)
392             .setSummaryResId(android.R.string.autofill)
393             .build()
394 
395     /** Source provided by [staticSourcesConfig]. */
396     val staticSource2 =
397         staticSafetySourceBuilder("test_static_source_id_2")
398             .setTitleResId(android.R.string.copyUrl)
399             .setSummaryResId(android.R.string.cut)
400             .build()
401 
402     /**
403      * Source group provided by [staticSourcesConfig] containing a single source [staticSource1].
404      */
405     val staticSourceGroup1 =
406         staticSafetySourcesGroupBuilder("test_static_sources_group_id_1")
407             .addSafetySource(staticSource1)
408             .build()
409 
410     /**
411      * Source group provided by [staticSourcesConfig] containing a single source [staticSource2].
412      */
413     val staticSourceGroup2 =
414         staticSafetySourcesGroupBuilder("test_static_sources_group_id_2")
415             .setTitleResId(android.R.string.copy)
416             .addSafetySource(staticSource2)
417             .build()
418 
419     /** A simple [SafetyCenterConfig] for tests with static sources. */
420     val staticSourcesConfig =
421         SafetyCenterConfig.Builder()
422             .addSafetySourcesGroup(staticSourceGroup1)
423             .addSafetySourcesGroup(staticSourceGroup2)
424             .build()
425 
426     /**
427      * A [SafetyCenterConfig] with a single static source
428      *
429      * The particular source ID is configured in the same way as sources hosted by the Settings app,
430      * to launch as if it is part of the Settings app UI.
431      */
432     val singleStaticSettingsSourceConfig =
433         SafetyCenterConfig.Builder()
434             .addSafetySourcesGroup(
435                 staticSafetySourcesGroupBuilder("single_static_source_group")
436                     .addSafetySource(staticSafetySource("TestSource"))
437                     .build()
438             )
439             .build()
440 
441     /** A [SafetyCenterConfig] with a single static source and an intent that doesn't resolve */
442     val singleStaticInvalidIntentConfig =
443         SafetyCenterConfig.Builder()
444             .addSafetySourcesGroup(
445                 staticSafetySourcesGroupBuilder("single_static_source_group")
446                     .addSafetySource(
447                         staticSafetySourceBuilder(SINGLE_SOURCE_ID)
448                             .setIntentAction(INTENT_ACTION_NOT_RESOLVING)
449                             .build()
450                     )
451                     .build()
452             )
453             .build()
454 
455     /**
456      * A [SafetyCenterConfig] with a single static source and an implicit intent that isn't exported
457      */
458     val singleStaticImplicitIntentNotExportedConfig =
459         SafetyCenterConfig.Builder()
460             .addSafetySourcesGroup(
461                 staticSafetySourcesGroupBuilder("single_static_source_group")
462                     .addSafetySource(
463                         staticSafetySourceBuilder(SINGLE_SOURCE_ID)
464                             .setIntentAction(ACTION_TEST_ACTIVITY)
465                             .build()
466                     )
467                     .build()
468             )
469             .build()
470 
471     /** [SafetyCenterConfig] used in tests for Your Work Policy Info source. */
472     val workPolicyInfoConfig =
473         SafetyCenterConfig.Builder()
474             .addSafetySourcesGroup(
475                 SafetySourcesGroup.Builder()
476                     .setId("AndroidAdvancedSources")
477                     .setTitleResId(android.R.string.paste)
478                     .addSafetySource(
479                         SafetySource.Builder(SAFETY_SOURCE_TYPE_DYNAMIC)
480                             .setId("AndroidWorkPolicyInfo")
481                             .setPackageName(context.packageManager.permissionControllerPackageName)
482                             .setProfile(SafetySource.PROFILE_PRIMARY)
483                             .setRefreshOnPageOpenAllowed(true)
484                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
485                             .build()
486                     )
487                     .build()
488             )
489             .build()
490 
491     /** [SafetyCenterConfig] used in tests to replicate the lock screen source. */
492     val settingsLockScreenSourceConfig =
493         SafetyCenterConfig.Builder()
494             .addSafetySourcesGroup(
495                 safetySourcesGroupBuilder(ANDROID_LOCK_SCREEN_SOURCES_GROUP_ID)
496                     .addSafetySource(
497                         dynamicSafetySourceBuilder("AndroidLockScreen")
498                             .setPackageName(context.getSettingsPackageName())
499                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
500                             .build()
501                     )
502                     .build()
503             )
504             .build()
505 
506     /** [SafetyCenterConfig] used in tests to replicate the lock screen sources group. */
507     val androidLockScreenSourcesConfig =
508         SafetyCenterConfig.Builder()
509             .addSafetySourcesGroup(
510                 safetySourcesGroupBuilder(ANDROID_LOCK_SCREEN_SOURCES_GROUP_ID)
511                     // This is needed to have a stateful group with an empty summary
512                     .setSummaryResId(Resources.ID_NULL)
513                     .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
514                     .addSafetySource(
515                         dynamicSafetySourceBuilder(DYNAMIC_BAREBONE_ID)
516                             .setRefreshOnPageOpenAllowed(false)
517                             .build()
518                     )
519                     .addSafetySource(
520                         dynamicSafetySourceBuilder(DYNAMIC_HIDDEN_ID)
521                             .setTitleResId(Resources.ID_NULL)
522                             .setSummaryResId(Resources.ID_NULL)
523                             .setIntentAction(null)
524                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
525                             .build()
526                     )
527                     .addSafetySource(
528                         dynamicSafetySourceBuilder(DYNAMIC_DISABLED_ID)
529                             .setIntentAction(null)
530                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
531                             .build()
532                     )
533                     .build()
534             )
535             .build()
536 
537     /** A simple [SafetyCenterConfig] used in tests that stress the group summary logic. */
538     val summaryTestConfig =
539         SafetyCenterConfig.Builder()
540             .addSafetySourcesGroup(
541                 safetySourcesGroupBuilder(SUMMARY_TEST_GROUP_ID)
542                     .addSafetySource(dynamicSafetySource(SOURCE_ID_1))
543                     .addSafetySource(dynamicSafetySource(SOURCE_ID_2))
544                     .addSafetySource(dynamicSafetySource(SOURCE_ID_3))
545                     .addSafetySource(dynamicSafetySource(SOURCE_ID_4))
546                     .addSafetySource(dynamicSafetySource(SOURCE_ID_5))
547                     .addSafetySource(dynamicSafetySource(SOURCE_ID_6))
548                     .addSafetySource(dynamicSafetySource(SOURCE_ID_7))
549                     .addSafetySource(staticSafetySource(STATIC_IN_STATEFUL_ID))
550                     .build()
551             )
552             .build()
553 
554     /**
555      * A complex [SafetyCenterConfig] exploring different combinations of valid sources and groups.
556      */
557     val complexConfig =
558         SafetyCenterConfig.Builder()
559             .addSafetySourcesGroup(
560                 safetySourcesGroupBuilder(DYNAMIC_GROUP_ID)
561                     .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
562                     .addSafetySource(
563                         dynamicSafetySourceBuilder(DYNAMIC_BAREBONE_ID)
564                             .setRefreshOnPageOpenAllowed(false)
565                             .build()
566                     )
567                     .addSafetySource(
568                         dynamicSafetySourceBuilder(DYNAMIC_ALL_OPTIONAL_ID)
569                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
570                             .setMaxSeverityLevel(SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION)
571                             .setSearchTermsResId(android.R.string.ok)
572                             .setLoggingAllowed(false)
<lambda>null573                             .apply {
574                                 if (SdkLevel.isAtLeastU()) {
575                                     setNotificationsAllowed(true)
576                                     setDeduplicationGroup("group")
577                                     addPackageCertificateHash(PACKAGE_CERT_HASH_FAKE)
578                                     addPackageCertificateHash(packageCertHash)
579                                 }
580                             }
581                             .build()
582                     )
583                     .addSafetySource(
584                         dynamicSafetySourceBuilder(DYNAMIC_DISABLED_ID)
585                             .setIntentAction(null)
586                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
587                             .build()
588                     )
589                     .addSafetySource(
590                         dynamicSafetySourceBuilder(DYNAMIC_HIDDEN_ID)
591                             .setTitleResId(Resources.ID_NULL)
592                             .setSummaryResId(Resources.ID_NULL)
593                             .setIntentAction(null)
594                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
595                             .build()
596                     )
597                     .addSafetySource(
598                         dynamicSafetySourceBuilder(DYNAMIC_HIDDEN_WITH_SEARCH_ID)
599                             .setSummaryResId(Resources.ID_NULL)
600                             .setIntentAction(null)
601                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
602                             .setSearchTermsResId(android.R.string.ok)
603                             .build()
604                     )
605                     .addSafetySource(dynamicOtherPackageSafetySource)
606                     .build()
607             )
608             .addSafetySourcesGroup(
609                 safetySourcesGroupBuilder(STATIC_GROUP_ID)
<lambda>null610                     .apply {
611                         if (SdkLevel.isAtLeastU()) {
612                             setType(SafetySourcesGroup.SAFETY_SOURCES_GROUP_TYPE_STATELESS)
613                             setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
614                         } else {
615                             setSummaryResId(Resources.ID_NULL)
616                         }
617                     }
618                     .addSafetySource(
619                         staticSafetySourceBuilder(STATIC_BAREBONE_ID)
620                             .setSummaryResId(Resources.ID_NULL)
621                             .build()
622                     )
623                     .addSafetySource(
624                         staticSafetySourceBuilder(STATIC_ALL_OPTIONAL_ID)
625                             .setSearchTermsResId(android.R.string.ok)
<lambda>null626                             .apply {
627                                 if (SdkLevel.isAtLeastU()) setPackageName(context.packageName)
628                             }
629                             .build()
630                     )
631                     .build()
632             )
633             .addSafetySourcesGroup(
634                 SafetySourcesGroup.Builder()
635                     .setId(ISSUE_ONLY_GROUP_ID)
<lambda>null636                     .apply {
637                         if (SdkLevel.isAtLeastU()) {
638                             setType(SafetySourcesGroup.SAFETY_SOURCES_GROUP_TYPE_HIDDEN)
639                             setTitleResId(android.R.string.ok)
640                             setSummaryResId(android.R.string.ok)
641                             setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
642                         }
643                     }
644                     .addSafetySource(
645                         issueOnlySafetySourceBuilder(ISSUE_ONLY_BAREBONE_ID)
646                             .setRefreshOnPageOpenAllowed(false)
647                             .build()
648                     )
649                     .addSafetySource(
650                         issueOnlySafetySourceBuilder(ISSUE_ONLY_ALL_OPTIONAL_ID)
651                             .setMaxSeverityLevel(SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION)
652                             .setLoggingAllowed(false)
<lambda>null653                             .apply {
654                                 if (SdkLevel.isAtLeastU()) {
655                                     setNotificationsAllowed(true)
656                                     setDeduplicationGroup("group")
657                                     addPackageCertificateHash(PACKAGE_CERT_HASH_FAKE)
658                                     addPackageCertificateHash(packageCertHash)
659                                 }
660                             }
661                             .build()
662                     )
663                     .build()
664             )
665             .addSafetySourcesGroup(
666                 safetySourcesGroupBuilder(MIXED_STATEFUL_GROUP_ID)
667                     .addSafetySource(dynamicSafetySource(DYNAMIC_IN_STATEFUL_ID))
668                     .addSafetySource(staticSafetySource(STATIC_IN_STATEFUL_ID))
669                     .build()
670             )
671             .addSafetySourcesGroup(
672                 safetySourcesGroupBuilder(MIXED_STATELESS_GROUP_ID)
673                     .setSummaryResId(Resources.ID_NULL)
674                     .addSafetySource(dynamicSafetySource(DYNAMIC_IN_STATELESS_ID))
675                     .addSafetySource(staticSafetySource(STATIC_IN_STATELESS_ID))
676                     .addSafetySource(issueOnlySafetySource(ISSUE_ONLY_IN_STATELESS_ID))
677                     .build()
678             )
679             .build()
680 
681     /**
682      * A complex [SafetyCenterConfig] exploring different combinations of valid sources and groups.
683      * Including sources that support all profiles.
684      */
685     val complexAllProfileConfig =
686         SafetyCenterConfig.Builder()
687             .addSafetySourcesGroup(
688                 safetySourcesGroupBuilder(DYNAMIC_GROUP_ID)
689                     .addSafetySource(
690                         dynamicSafetySourceBuilder(DYNAMIC_BAREBONE_ID)
691                             .setRefreshOnPageOpenAllowed(false)
692                             .build()
693                     )
694                     .addSafetySource(
695                         dynamicAllProfileSafetySourceBuilder(DYNAMIC_DISABLED_ID)
696                             .setIntentAction(null)
697                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
698                             .build()
699                     )
700                     .addSafetySource(
701                         dynamicAllProfileSafetySourceBuilder(DYNAMIC_HIDDEN_ID)
702                             .setTitleResId(Resources.ID_NULL)
703                             .setTitleForWorkResId(Resources.ID_NULL)
704                             .setSummaryResId(Resources.ID_NULL)
705                             .setIntentAction(null)
706                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
<lambda>null707                             .apply {
708                                 if (SdkLevel.isAtLeastV() && Flags.privateProfileTitleApi()) {
709                                     setTitleForPrivateProfileResId(Resources.ID_NULL)
710                                 }
711                             }
712                             .build()
713                     )
714                     .build()
715             )
716             .addSafetySourcesGroup(
717                 safetySourcesGroupBuilder(STATIC_GROUP_ID)
718                     .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
719                     .addSafetySource(
720                         staticSafetySourceBuilder(STATIC_BAREBONE_ID)
721                             .setSummaryResId(Resources.ID_NULL)
722                             .build()
723                     )
724                     .addSafetySource(
725                         staticAllProfileSafetySourceBuilder(STATIC_ALL_OPTIONAL_ID)
726                             .setSearchTermsResId(android.R.string.ok)
<lambda>null727                             .apply {
728                                 if (SdkLevel.isAtLeastU()) setPackageName(context.packageName)
729                             }
730                             .build()
731                     )
732                     .build()
733             )
734             .addSafetySourcesGroup(
735                 SafetySourcesGroup.Builder()
736                     .setId(ISSUE_ONLY_GROUP_ID)
737                     .addSafetySource(
738                         issueOnlySafetySourceBuilder(ISSUE_ONLY_BAREBONE_ID)
739                             .setRefreshOnPageOpenAllowed(false)
740                             .build()
741                     )
742                     .addSafetySource(
743                         issueOnlyAllProfileSafetySourceBuilder(ISSUE_ONLY_ALL_OPTIONAL_ID)
744                             .setMaxSeverityLevel(SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION)
745                             .setLoggingAllowed(false)
<lambda>null746                             .apply {
747                                 if (SdkLevel.isAtLeastU()) {
748                                     setNotificationsAllowed(true)
749                                     setDeduplicationGroup("group")
750                                     addPackageCertificateHash(PACKAGE_CERT_HASH_FAKE)
751                                     addPackageCertificateHash(packageCertHash)
752                                 }
753                             }
754                             .build()
755                     )
756                     .build()
757             )
758             .addSafetySourcesGroup(
759                 safetySourcesGroupBuilder(MIXED_STATELESS_GROUP_ID)
760                     .setSummaryResId(Resources.ID_NULL)
761                     .addSafetySource(
762                         dynamicAllProfileSafetySourceBuilder(DYNAMIC_IN_STATELESS_ID).build()
763                     )
764                     .addSafetySource(
765                         staticAllProfileSafetySourceBuilder(STATIC_IN_STATELESS_ID).build()
766                     )
767                     .addSafetySource(
768                         issueOnlyAllProfileSafetySourceBuilder(ISSUE_ONLY_IN_STATELESS_ID).build()
769                     )
770                     .build()
771             )
772             .build()
773 
774     /** A [SafetyCenterConfig] containing only hidden sources. */
775     val hiddenOnlyConfig =
776         SafetyCenterConfig.Builder()
777             .addSafetySourcesGroup(
778                 safetySourcesGroupBuilder("some_collapsible_group")
779                     .addSafetySource(
780                         dynamicSafetySourceBuilder("some_hidden_source")
781                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
782                             .build()
783                     )
784                     .build()
785             )
786             .addSafetySourcesGroup(
787                 safetySourcesGroupBuilder("some_rigid_group")
788                     .setSummaryResId(Resources.ID_NULL)
789                     .addSafetySource(
790                         dynamicSafetySourceBuilder("another_hidden_source")
791                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
792                             .build()
793                     )
794                     .build()
795             )
796             .build()
797 
dynamicSafetySourcenull798     private fun dynamicSafetySource(id: String) = dynamicSafetySourceBuilder(id).build()
799 
800     fun dynamicSafetySourceBuilder(id: String) =
801         SafetySource.Builder(SAFETY_SOURCE_TYPE_DYNAMIC)
802             .setId(id)
803             .setPackageName(context.packageName)
804             .setTitleResId(android.R.string.ok)
805             .setSummaryResId(android.R.string.ok)
806             .setIntentAction(ACTION_TEST_ACTIVITY)
807             .setProfile(SafetySource.PROFILE_PRIMARY)
808             .setRefreshOnPageOpenAllowed(true)
809 
810     private fun dynamicAllProfileSafetySourceBuilder(id: String) =
811         dynamicSafetySourceBuilder(id)
812             .setProfile(SafetySource.PROFILE_ALL)
813             .setTitleForWorkResId(android.R.string.paste)
814             .apply {
815                 if (SdkLevel.isAtLeastV() && Flags.privateProfileTitleApi()) {
816                     setTitleForPrivateProfileResId(android.R.string.unknownName)
817                 }
818             }
819 
staticSafetySourcenull820     private fun staticSafetySource(id: String) = staticSafetySourceBuilder(id).build()
821 
822     private fun staticSafetySourceBuilder(id: String) =
823         SafetySource.Builder(SAFETY_SOURCE_TYPE_STATIC)
824             .setId(id)
825             .setTitleResId(android.R.string.ok)
826             .setSummaryResId(android.R.string.ok)
827             .setIntentAction(ACTION_TEST_ACTIVITY_EXPORTED)
828             .setProfile(SafetySource.PROFILE_PRIMARY)
829 
830     private fun staticAllProfileSafetySourceBuilder(id: String) =
831         staticSafetySourceBuilder(id)
832             .setProfile(SafetySource.PROFILE_ALL)
833             .setTitleForWorkResId(android.R.string.paste)
834             .apply {
835                 if (SdkLevel.isAtLeastV() && Flags.privateProfileTitleApi()) {
836                     setTitleForPrivateProfileResId(android.R.string.unknownName)
837                 }
838             }
839 
840     @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
issueOnlySafetySourceWithDuplicationInfonull841     private fun issueOnlySafetySourceWithDuplicationInfo(id: String, deduplicationGroup: String) =
842         issueOnlySafetySourceBuilder(id).setDeduplicationGroup(deduplicationGroup).build()
843 
844     private fun issueOnlySafetySource(id: String) = issueOnlySafetySourceBuilder(id).build()
845 
846     private fun issueOnlySafetySourceBuilder(id: String) =
847         SafetySource.Builder(SAFETY_SOURCE_TYPE_ISSUE_ONLY)
848             .setId(id)
849             .setPackageName(context.packageName)
850             .setProfile(SafetySource.PROFILE_PRIMARY)
851             .setRefreshOnPageOpenAllowed(true)
852 
853     private fun issueOnlyAllProfileSafetySourceBuilder(id: String) =
854         issueOnlySafetySourceBuilder(id).setProfile(SafetySource.PROFILE_ALL)
855 
856     private fun safetySourcesGroupBuilder(id: String) =
857         SafetySourcesGroup.Builder()
858             .setId(id)
859             .setTitleResId(android.R.string.ok)
860             .setSummaryResId(android.R.string.ok)
861 
862     private fun staticSafetySourcesGroupBuilder(id: String) =
863         SafetySourcesGroup.Builder().setId(id).setTitleResId(android.R.string.paste)
864 
865     fun singleSourceConfig(safetySource: SafetySource) =
866         SafetyCenterConfig.Builder()
867             .addSafetySourcesGroup(
868                 safetySourcesGroupBuilder(SINGLE_SOURCE_GROUP_ID)
869                     .addSafetySource(safetySource)
870                     .build()
871             )
872             .build()
873 
874     companion object {
875         /** ID of a source not used in any config. */
876         const val SAMPLE_SOURCE_ID = "test_sample_source_id"
877 
878         /** Activity action: Launches the [TestActivity] used to check redirects in tests. */
879         const val ACTION_TEST_ACTIVITY = "com.android.safetycenter.testing.action.TEST_ACTIVITY"
880 
881         /**
882          * Activity action: Launches the [TestActivity] used to check redirects in tests, but with
883          * an exported activity alias.
884          */
885         const val ACTION_TEST_ACTIVITY_EXPORTED =
886             "com.android.safetycenter.testing.action.TEST_ACTIVITY_EXPORTED"
887 
888         /**
889          * ID of the only source provided in [singleSourceConfig], [severityZeroConfig] and
890          * [noPageOpenConfig].
891          */
892         // LINT.IfChange(single_source_id)
893         const val SINGLE_SOURCE_ID = "test_single_source_id"
894         // LINT.ThenChange(/tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetyCenterInteractionLoggingHostTest.kt:single_source_id)
895 
896         /** ID of the only source provided in [singleSourceAllProfileConfig]. */
897         const val SINGLE_SOURCE_ALL_PROFILE_ID = "test_single_source_all_profile_id"
898 
899         /** ID of the only source provided in [issueOnlySourceAllProfileConfig]. */
900         const val ISSUE_ONLY_ALL_PROFILE_SOURCE_ID = "test_issue_only_all_profile_id"
901 
902         /**
903          * ID of the only [SafetySourcesGroup] provided by [singleSourceConfig],
904          * [severityZeroConfig] and [noPageOpenConfig].
905          */
906         const val SINGLE_SOURCE_GROUP_ID = "test_single_source_group_id"
907 
908         /**
909          * SHA256 hash of a package certificate.
910          *
911          * <p>This is a fake certificate, and can be used to test failure cases, or to test a list
912          * of certificates when only one match is required.
913          */
914         const val PACKAGE_CERT_HASH_FAKE = "feed12"
915 
916         /** An invalid SHA256 hash (not a byte string, not even number of chars). */
917         const val PACKAGE_CERT_HASH_INVALID = "0124ppl"
918 
919         /** ID of a source provided by [multipleSourcesConfig] and [summaryTestConfig]. */
920         const val SOURCE_ID_1 = "test_source_id_1"
921 
922         /** ID of a source provided by [multipleSourcesConfig] and [summaryTestConfig]. */
923         const val SOURCE_ID_2 = "test_source_id_2"
924 
925         /** ID of a source provided by [multipleSourcesConfig] and [summaryTestConfig]. */
926         const val SOURCE_ID_3 = "test_source_id_3"
927 
928         /** ID of a source provided by [summaryTestConfig]. */
929         const val SOURCE_ID_4 = "test_source_id_4"
930 
931         /** ID of a source provided by [summaryTestConfig]. */
932         const val SOURCE_ID_5 = "test_source_id_5"
933 
934         /** ID of a source provided by [summaryTestConfig]. */
935         const val SOURCE_ID_6 = "test_source_id_6"
936 
937         /** ID of a source provided by [summaryTestConfig]. */
938         const val SOURCE_ID_7 = "test_source_id_7"
939 
940         /**
941          * ID of a source provided by [privacySubpageConfig] and
942          * [privacySubpageWithoutDataSourcesConfig].
943          */
944         const val PRIVACY_SOURCE_ID_1 = "AndroidPermissionUsage"
945 
946         /**
947          * ID of a [SafetySourcesGroup] provided by [multipleSourcesConfig], containing two sources
948          * of ids [SOURCE_ID_1] and [SOURCE_ID_2].
949          */
950         const val MULTIPLE_SOURCES_GROUP_ID_1 = "test_multiple_sources_group_id_1"
951 
952         /**
953          * ID of a [SafetySourcesGroup] provided by [multipleSourcesConfig], containing a single
954          * source of id [SOURCE_ID_3].
955          */
956         const val MULTIPLE_SOURCES_GROUP_ID_2 = "test_multiple_sources_group_id_2"
957 
958         /**
959          * ID of a [SafetySourcesGroup] provided by [multipleSourcesConfig], containing two sources
960          * of ids [SOURCE_ID_4] and [SOURCE_ID_5].
961          */
962         const val MULTIPLE_SOURCES_GROUP_ID_3 = "test_multiple_sources_group_id_3"
963 
964         /**
965          * ID of a [SafetySourcesGroup] provided by [summaryTestGroupConfig], containing sources:
966          * [SOURCE_ID_1], [SOURCE_ID_2], [SOURCE_ID_3], [SOURCE_ID_4], [SOURCE_ID_5], [SOURCE_ID_6],
967          * [SOURCE_ID_7], [STATIC_IN_STATEFUL_ID].
968          */
969         const val SUMMARY_TEST_GROUP_ID = "summary_test_group_id"
970 
971         /**
972          * ID of a [SafetySourcesGroup] provided by [complexConfig], containing sources:
973          * [DYNAMIC_BAREBONE_ID], [DYNAMIC_ALL_OPTIONAL_ID], [DYNAMIC_DISABLED_ID],
974          * [DYNAMIC_HIDDEN_ID], [DYNAMIC_HIDDEN_WITH_SEARCH_ID], [DYNAMIC_OTHER_PACKAGE_ID]. And
975          * provided by [complexAllProfileConfig], containing sources: [DYNAMIC_BAREBONE_ID],
976          * [DYNAMIC_DISABLED_ID], [DYNAMIC_HIDDEN_ID].
977          */
978         const val DYNAMIC_GROUP_ID = "dynamic"
979 
980         /**
981          * ID of a [SafetySourcesGroup] provided by [complexConfig] and [complexAllProfileConfig],
982          * containing sources: [STATIC_BAREBONE_ID], [STATIC_ALL_OPTIONAL_ID].
983          */
984         const val STATIC_GROUP_ID = "static"
985 
986         /**
987          * ID of a [SafetySourcesGroup] provided by [complexConfig] and [complexAllProfileConfig],
988          * containing sources: [ISSUE_ONLY_BAREBONE_ID], [ISSUE_ONLY_ALL_OPTIONAL_ID].
989          */
990         const val ISSUE_ONLY_GROUP_ID = "issue_only"
991 
992         /**
993          * ID of a [SafetySourcesGroup] provided by [complexConfig], containing sources:
994          * [DYNAMIC_IN_STATEFUL_ID], [STATIC_IN_STATEFUL_ID].
995          */
996         const val MIXED_STATEFUL_GROUP_ID = "mixed_stateful"
997 
998         /**
999          * ID of a [SafetySourcesGroup] provided by [complexConfig] and [complexAllProfileConfig],
1000          * containing sources: [DYNAMIC_IN_STATELESS_ID], [STATIC_IN_STATELESS_ID],
1001          * [ISSUE_ONLY_IN_STATELESS_ID].
1002          */
1003         const val MIXED_STATELESS_GROUP_ID = "mixed_stateless"
1004 
1005         /**
1006          * ID of a source provided by [complexConfig], [complexAllProfileConfig], and
1007          * [androidLockScreenSourcesConfig], this is a dynamic, primary profile only, visible source
1008          * for which only the required fields are set.
1009          */
1010         const val DYNAMIC_BAREBONE_ID = "dynamic_barebone"
1011 
1012         /**
1013          * ID of a source provided by [complexConfig] and [singleSourceOtherPackageConfig], this is
1014          * a dynamic, primary profile only, visible source belonging to the [OTHER_PACKAGE_NAME]
1015          * package for which only the required fields are set.
1016          */
1017         const val DYNAMIC_OTHER_PACKAGE_ID = "dynamic_other_package"
1018 
1019         /**
1020          * ID of a source provided by [complexConfig], this is a dynamic, primary profile only,
1021          * disabled by default source for which all the required and optional fields are set.
1022          * Notably, this includes the refresh on page open flag and a max severity level of
1023          * recommendation.
1024          */
1025         const val DYNAMIC_ALL_OPTIONAL_ID = "dynamic_all_optional"
1026 
1027         /**
1028          * ID of a source provided by [complexConfig], [complexAllProfileConfig], and
1029          * [androidLockScreenSourcesConfig], this is a dynamic, disabled by default source for which
1030          * only the required fields are set.
1031          */
1032         const val DYNAMIC_DISABLED_ID = "dynamic_disabled"
1033 
1034         /**
1035          * ID of a source provided by [complexConfig], [complexAllProfileConfig], and
1036          * [androidLockScreenSourcesConfig], this ism a dynamic, hidden by default source for which
1037          * only the required fields are set.
1038          */
1039         const val DYNAMIC_HIDDEN_ID = "dynamic_hidden"
1040 
1041         /**
1042          * ID of a source provided by [complexConfig], this is a dynamic, primary profile only,
1043          * hidden by default source for which all the required and optional fields are set.
1044          */
1045         const val DYNAMIC_HIDDEN_WITH_SEARCH_ID = "dynamic_hidden_with_search"
1046 
1047         /**
1048          * ID of a source provided by [complexConfig] and [complexAllProfileConfig], this is a
1049          * static, primary profile only source for which only the required fields are set.
1050          */
1051         const val STATIC_BAREBONE_ID = "static_barebone"
1052 
1053         /**
1054          * ID of a source provided by [complexConfig] and [complexAllProfileConfig], this is a
1055          * static source for which all the required and optional fields are set.
1056          */
1057         const val STATIC_ALL_OPTIONAL_ID = "static_all_optional"
1058 
1059         /**
1060          * ID of a source provided by [complexConfig] and [complexAllProfileConfig], this is an
1061          * issue-only, primary profile only source for which only the required fields are set.
1062          */
1063         const val ISSUE_ONLY_BAREBONE_ID = "issue_only_barebone"
1064 
1065         /**
1066          * ID of a source provided by [complexConfig] and [complexAllProfileConfig], this is an
1067          * issue-only source for which all the required and optional fields are set. Notably, this
1068          * includes the refresh on page open flag and a max severity level of recommendation.
1069          */
1070         const val ISSUE_ONLY_ALL_OPTIONAL_ID = "issue_only_all_optional"
1071 
1072         /**
1073          * ID of a source provided by [complexConfig], this is a generic, dynamic, primary profile
1074          * only, visible source.
1075          */
1076         const val DYNAMIC_IN_STATEFUL_ID = "dynamic_in_stateful"
1077 
1078         /**
1079          * ID of a source provided by [complexConfig] and [complexAllProfileConfig], this is a
1080          * generic, dynamic, visible source.
1081          */
1082         const val DYNAMIC_IN_STATELESS_ID = "dynamic_in_stateless"
1083 
1084         /**
1085          * ID of a source provided by [complexConfig] and [complexAllProfileConfig], this is an
1086          * issue-only source.
1087          */
1088         const val ISSUE_ONLY_IN_STATELESS_ID = "issue_only_in_stateless"
1089 
1090         /**
1091          * ID of a source provided by [complexConfig] and [summaryTestConfig], this is a generic,
1092          * static, primary profile only source.
1093          */
1094         const val STATIC_IN_STATEFUL_ID = "static_in_stateful"
1095 
1096         /**
1097          * ID of a source provided by [complexConfig] and [complexAllProfileConfig], this is a
1098          * generic, static source.
1099          */
1100         const val STATIC_IN_STATELESS_ID = "static_in_stateless"
1101 
1102         /** Package name for the [DYNAMIC_OTHER_PACKAGE_ID] source. */
1103         const val OTHER_PACKAGE_NAME = "other_package_name"
1104 
1105         private const val DEDUPLICATION_GROUP_1 = "deduplication_group_1"
1106         private const val DEDUPLICATION_GROUP_2 = "deduplication_group_2"
1107         private const val DEDUPLICATION_GROUP_3 = "deduplication_group_3"
1108 
1109         /**
1110          * ID of a [SafetySourcesGroup] provided by [settingsLockScreenSourceConfig] and
1111          * [androidLockScreenSourcesConfig], to replicate the lock screen sources group.
1112          */
1113         const val ANDROID_LOCK_SCREEN_SOURCES_GROUP_ID = "AndroidLockScreenSources"
1114 
1115         /**
1116          * ID of a [SafetySourcesGroup] provided by [privacySubpageConfig] and
1117          * [privacySubpageWithoutDataSourcesConfig], to replicate the privacy sources group.
1118          */
1119         const val ANDROID_PRIVACY_SOURCES_GROUP_ID = "AndroidPrivacySources"
1120 
1121         private const val INTENT_ACTION_NOT_RESOLVING = "there.is.no.way.this.resolves"
1122     }
1123 }
1124