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 multiple sources with one source having an
355      * invalid default intent.
356      */
357     val multipleSourcesConfigWithSourceWithInvalidIntent =
358         SafetyCenterConfig.Builder()
359             .addSafetySourcesGroup(
360                 safetySourcesGroupBuilder(MULTIPLE_SOURCES_GROUP_ID_1)
361                     .addSafetySource(
362                         dynamicSafetySourceBuilder(SOURCE_ID_1)
363                             .setIntentAction(INTENT_ACTION_NOT_RESOLVING)
364                             .build()
365                     )
366                     .addSafetySource(dynamicSafetySource(SOURCE_ID_2))
367                     .build()
368             )
369             .build()
370 
371     /** Source provided by [staticSourcesConfig]. */
372     val staticSource1 =
373         staticSafetySourceBuilder("test_static_source_id_1")
374             .setTitleResId(android.R.string.dialog_alert_title)
375             .setSummaryResId(android.R.string.autofill)
376             .build()
377 
378     /** Source provided by [staticSourcesConfig]. */
379     val staticSource2 =
380         staticSafetySourceBuilder("test_static_source_id_2")
381             .setTitleResId(android.R.string.copyUrl)
382             .setSummaryResId(android.R.string.cut)
383             .build()
384 
385     /**
386      * Source group provided by [staticSourcesConfig] containing a single source [staticSource1].
387      */
388     val staticSourceGroup1 =
389         staticSafetySourcesGroupBuilder("test_static_sources_group_id_1")
390             .addSafetySource(staticSource1)
391             .build()
392 
393     /**
394      * Source group provided by [staticSourcesConfig] containing a single source [staticSource2].
395      */
396     val staticSourceGroup2 =
397         staticSafetySourcesGroupBuilder("test_static_sources_group_id_2")
398             .setTitleResId(android.R.string.copy)
399             .addSafetySource(staticSource2)
400             .build()
401 
402     /** A simple [SafetyCenterConfig] for tests with static sources. */
403     val staticSourcesConfig =
404         SafetyCenterConfig.Builder()
405             .addSafetySourcesGroup(staticSourceGroup1)
406             .addSafetySourcesGroup(staticSourceGroup2)
407             .build()
408 
409     /**
410      * A [SafetyCenterConfig] with a single static source
411      *
412      * The particular source ID is configured in the same way as sources hosted by the Settings app,
413      * to launch as if it is part of the Settings app UI.
414      */
415     val singleStaticSettingsSourceConfig =
416         SafetyCenterConfig.Builder()
417             .addSafetySourcesGroup(
418                 staticSafetySourcesGroupBuilder("single_static_source_group")
419                     .addSafetySource(staticSafetySource("TestSource"))
420                     .build()
421             )
422             .build()
423 
424     /** A [SafetyCenterConfig] with a single static source and an intent that doesn't resolve */
425     val singleStaticInvalidIntentConfig =
426         SafetyCenterConfig.Builder()
427             .addSafetySourcesGroup(
428                 staticSafetySourcesGroupBuilder("single_static_source_group")
429                     .addSafetySource(
430                         staticSafetySourceBuilder(SINGLE_SOURCE_ID)
431                             .setIntentAction(INTENT_ACTION_NOT_RESOLVING)
432                             .build()
433                     )
434                     .build()
435             )
436             .build()
437 
438     /**
439      * A [SafetyCenterConfig] with a single static source and an implicit intent that isn't exported
440      */
441     val singleStaticImplicitIntentNotExportedConfig =
442         SafetyCenterConfig.Builder()
443             .addSafetySourcesGroup(
444                 staticSafetySourcesGroupBuilder("single_static_source_group")
445                     .addSafetySource(
446                         staticSafetySourceBuilder(SINGLE_SOURCE_ID)
447                             .setIntentAction(ACTION_TEST_ACTIVITY)
448                             .build()
449                     )
450                     .build()
451             )
452             .build()
453 
454     /** [SafetyCenterConfig] used in tests for Your Work Policy Info source. */
455     val workPolicyInfoConfig =
456         SafetyCenterConfig.Builder()
457             .addSafetySourcesGroup(
458                 SafetySourcesGroup.Builder()
459                     .setId("AndroidAdvancedSources")
460                     .setTitleResId(android.R.string.paste)
461                     .addSafetySource(
462                         SafetySource.Builder(SAFETY_SOURCE_TYPE_DYNAMIC)
463                             .setId("AndroidWorkPolicyInfo")
464                             .setPackageName(context.packageManager.permissionControllerPackageName)
465                             .setProfile(SafetySource.PROFILE_PRIMARY)
466                             .setRefreshOnPageOpenAllowed(true)
467                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
468                             .build()
469                     )
470                     .build()
471             )
472             .build()
473 
474     /** [SafetyCenterConfig] used in tests to replicate the lock screen source. */
475     val settingsLockScreenSourceConfig =
476         SafetyCenterConfig.Builder()
477             .addSafetySourcesGroup(
478                 safetySourcesGroupBuilder(ANDROID_LOCK_SCREEN_SOURCES_GROUP_ID)
479                     .addSafetySource(
480                         dynamicSafetySourceBuilder("AndroidLockScreen")
481                             .setPackageName(context.getSettingsPackageName())
482                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
483                             .build()
484                     )
485                     .build()
486             )
487             .build()
488 
489     /** [SafetyCenterConfig] used in tests to replicate the lock screen sources group. */
490     val androidLockScreenSourcesConfig =
491         SafetyCenterConfig.Builder()
492             .addSafetySourcesGroup(
493                 safetySourcesGroupBuilder(ANDROID_LOCK_SCREEN_SOURCES_GROUP_ID)
494                     // This is needed to have a stateful group with an empty summary
495                     .setSummaryResId(Resources.ID_NULL)
496                     .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
497                     .addSafetySource(
498                         dynamicSafetySourceBuilder(DYNAMIC_BAREBONE_ID)
499                             .setRefreshOnPageOpenAllowed(false)
500                             .build()
501                     )
502                     .addSafetySource(
503                         dynamicSafetySourceBuilder(DYNAMIC_HIDDEN_ID)
504                             .setTitleResId(Resources.ID_NULL)
505                             .setSummaryResId(Resources.ID_NULL)
506                             .setIntentAction(null)
507                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
508                             .build()
509                     )
510                     .addSafetySource(
511                         dynamicSafetySourceBuilder(DYNAMIC_DISABLED_ID)
512                             .setIntentAction(null)
513                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
514                             .build()
515                     )
516                     .build()
517             )
518             .build()
519 
520     /** A simple [SafetyCenterConfig] used in tests that stress the group summary logic. */
521     val summaryTestConfig =
522         SafetyCenterConfig.Builder()
523             .addSafetySourcesGroup(
524                 safetySourcesGroupBuilder(SUMMARY_TEST_GROUP_ID)
525                     .addSafetySource(dynamicSafetySource(SOURCE_ID_1))
526                     .addSafetySource(dynamicSafetySource(SOURCE_ID_2))
527                     .addSafetySource(dynamicSafetySource(SOURCE_ID_3))
528                     .addSafetySource(dynamicSafetySource(SOURCE_ID_4))
529                     .addSafetySource(dynamicSafetySource(SOURCE_ID_5))
530                     .addSafetySource(dynamicSafetySource(SOURCE_ID_6))
531                     .addSafetySource(dynamicSafetySource(SOURCE_ID_7))
532                     .addSafetySource(staticSafetySource(STATIC_IN_STATEFUL_ID))
533                     .build()
534             )
535             .build()
536 
537     /**
538      * A complex [SafetyCenterConfig] exploring different combinations of valid sources and groups.
539      */
540     val complexConfig =
541         SafetyCenterConfig.Builder()
542             .addSafetySourcesGroup(
543                 safetySourcesGroupBuilder(DYNAMIC_GROUP_ID)
544                     .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
545                     .addSafetySource(
546                         dynamicSafetySourceBuilder(DYNAMIC_BAREBONE_ID)
547                             .setRefreshOnPageOpenAllowed(false)
548                             .build()
549                     )
550                     .addSafetySource(
551                         dynamicSafetySourceBuilder(DYNAMIC_ALL_OPTIONAL_ID)
552                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
553                             .setMaxSeverityLevel(SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION)
554                             .setSearchTermsResId(android.R.string.ok)
555                             .setLoggingAllowed(false)
<lambda>null556                             .apply {
557                                 if (SdkLevel.isAtLeastU()) {
558                                     setNotificationsAllowed(true)
559                                     setDeduplicationGroup("group")
560                                     addPackageCertificateHash(PACKAGE_CERT_HASH_FAKE)
561                                     addPackageCertificateHash(packageCertHash)
562                                 }
563                             }
564                             .build()
565                     )
566                     .addSafetySource(
567                         dynamicSafetySourceBuilder(DYNAMIC_DISABLED_ID)
568                             .setIntentAction(null)
569                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
570                             .build()
571                     )
572                     .addSafetySource(
573                         dynamicSafetySourceBuilder(DYNAMIC_HIDDEN_ID)
574                             .setTitleResId(Resources.ID_NULL)
575                             .setSummaryResId(Resources.ID_NULL)
576                             .setIntentAction(null)
577                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
578                             .build()
579                     )
580                     .addSafetySource(
581                         dynamicSafetySourceBuilder(DYNAMIC_HIDDEN_WITH_SEARCH_ID)
582                             .setSummaryResId(Resources.ID_NULL)
583                             .setIntentAction(null)
584                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
585                             .setSearchTermsResId(android.R.string.ok)
586                             .build()
587                     )
588                     .addSafetySource(dynamicOtherPackageSafetySource)
589                     .build()
590             )
591             .addSafetySourcesGroup(
592                 safetySourcesGroupBuilder(STATIC_GROUP_ID)
<lambda>null593                     .apply {
594                         if (SdkLevel.isAtLeastU()) {
595                             setType(SafetySourcesGroup.SAFETY_SOURCES_GROUP_TYPE_STATELESS)
596                             setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
597                         } else {
598                             setSummaryResId(Resources.ID_NULL)
599                         }
600                     }
601                     .addSafetySource(
602                         staticSafetySourceBuilder(STATIC_BAREBONE_ID)
603                             .setSummaryResId(Resources.ID_NULL)
604                             .build()
605                     )
606                     .addSafetySource(
607                         staticSafetySourceBuilder(STATIC_ALL_OPTIONAL_ID)
608                             .setSearchTermsResId(android.R.string.ok)
<lambda>null609                             .apply {
610                                 if (SdkLevel.isAtLeastU()) setPackageName(context.packageName)
611                             }
612                             .build()
613                     )
614                     .build()
615             )
616             .addSafetySourcesGroup(
617                 SafetySourcesGroup.Builder()
618                     .setId(ISSUE_ONLY_GROUP_ID)
<lambda>null619                     .apply {
620                         if (SdkLevel.isAtLeastU()) {
621                             setType(SafetySourcesGroup.SAFETY_SOURCES_GROUP_TYPE_HIDDEN)
622                             setTitleResId(android.R.string.ok)
623                             setSummaryResId(android.R.string.ok)
624                             setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
625                         }
626                     }
627                     .addSafetySource(
628                         issueOnlySafetySourceBuilder(ISSUE_ONLY_BAREBONE_ID)
629                             .setRefreshOnPageOpenAllowed(false)
630                             .build()
631                     )
632                     .addSafetySource(
633                         issueOnlySafetySourceBuilder(ISSUE_ONLY_ALL_OPTIONAL_ID)
634                             .setMaxSeverityLevel(SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION)
635                             .setLoggingAllowed(false)
<lambda>null636                             .apply {
637                                 if (SdkLevel.isAtLeastU()) {
638                                     setNotificationsAllowed(true)
639                                     setDeduplicationGroup("group")
640                                     addPackageCertificateHash(PACKAGE_CERT_HASH_FAKE)
641                                     addPackageCertificateHash(packageCertHash)
642                                 }
643                             }
644                             .build()
645                     )
646                     .build()
647             )
648             .addSafetySourcesGroup(
649                 safetySourcesGroupBuilder(MIXED_STATEFUL_GROUP_ID)
650                     .addSafetySource(dynamicSafetySource(DYNAMIC_IN_STATEFUL_ID))
651                     .addSafetySource(staticSafetySource(STATIC_IN_STATEFUL_ID))
652                     .build()
653             )
654             .addSafetySourcesGroup(
655                 safetySourcesGroupBuilder(MIXED_STATELESS_GROUP_ID)
656                     .setSummaryResId(Resources.ID_NULL)
657                     .addSafetySource(dynamicSafetySource(DYNAMIC_IN_STATELESS_ID))
658                     .addSafetySource(staticSafetySource(STATIC_IN_STATELESS_ID))
659                     .addSafetySource(issueOnlySafetySource(ISSUE_ONLY_IN_STATELESS_ID))
660                     .build()
661             )
662             .build()
663 
664     /**
665      * A complex [SafetyCenterConfig] exploring different combinations of valid sources and groups.
666      * Including sources that support all profiles.
667      */
668     val complexAllProfileConfig =
669         SafetyCenterConfig.Builder()
670             .addSafetySourcesGroup(
671                 safetySourcesGroupBuilder(DYNAMIC_GROUP_ID)
672                     .addSafetySource(
673                         dynamicSafetySourceBuilder(DYNAMIC_BAREBONE_ID)
674                             .setRefreshOnPageOpenAllowed(false)
675                             .build()
676                     )
677                     .addSafetySource(
678                         dynamicAllProfileSafetySourceBuilder(DYNAMIC_DISABLED_ID)
679                             .setIntentAction(null)
680                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
681                             .build()
682                     )
683                     .addSafetySource(
684                         dynamicAllProfileSafetySourceBuilder(DYNAMIC_HIDDEN_ID)
685                             .setTitleResId(Resources.ID_NULL)
686                             .setTitleForWorkResId(Resources.ID_NULL)
687                             .setSummaryResId(Resources.ID_NULL)
688                             .setIntentAction(null)
689                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
<lambda>null690                             .apply {
691                                 if (SdkLevel.isAtLeastV() && Flags.privateProfileTitleApi()) {
692                                     setTitleForPrivateProfileResId(Resources.ID_NULL)
693                                 }
694                             }
695                             .build()
696                     )
697                     .build()
698             )
699             .addSafetySourcesGroup(
700                 safetySourcesGroupBuilder(STATIC_GROUP_ID)
701                     .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
702                     .addSafetySource(
703                         staticSafetySourceBuilder(STATIC_BAREBONE_ID)
704                             .setSummaryResId(Resources.ID_NULL)
705                             .build()
706                     )
707                     .addSafetySource(
708                         staticAllProfileSafetySourceBuilder(STATIC_ALL_OPTIONAL_ID)
709                             .setSearchTermsResId(android.R.string.ok)
<lambda>null710                             .apply {
711                                 if (SdkLevel.isAtLeastU()) setPackageName(context.packageName)
712                             }
713                             .build()
714                     )
715                     .build()
716             )
717             .addSafetySourcesGroup(
718                 SafetySourcesGroup.Builder()
719                     .setId(ISSUE_ONLY_GROUP_ID)
720                     .addSafetySource(
721                         issueOnlySafetySourceBuilder(ISSUE_ONLY_BAREBONE_ID)
722                             .setRefreshOnPageOpenAllowed(false)
723                             .build()
724                     )
725                     .addSafetySource(
726                         issueOnlyAllProfileSafetySourceBuilder(ISSUE_ONLY_ALL_OPTIONAL_ID)
727                             .setMaxSeverityLevel(SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION)
728                             .setLoggingAllowed(false)
<lambda>null729                             .apply {
730                                 if (SdkLevel.isAtLeastU()) {
731                                     setNotificationsAllowed(true)
732                                     setDeduplicationGroup("group")
733                                     addPackageCertificateHash(PACKAGE_CERT_HASH_FAKE)
734                                     addPackageCertificateHash(packageCertHash)
735                                 }
736                             }
737                             .build()
738                     )
739                     .build()
740             )
741             .addSafetySourcesGroup(
742                 safetySourcesGroupBuilder(MIXED_STATELESS_GROUP_ID)
743                     .setSummaryResId(Resources.ID_NULL)
744                     .addSafetySource(
745                         dynamicAllProfileSafetySourceBuilder(DYNAMIC_IN_STATELESS_ID).build()
746                     )
747                     .addSafetySource(
748                         staticAllProfileSafetySourceBuilder(STATIC_IN_STATELESS_ID).build()
749                     )
750                     .addSafetySource(
751                         issueOnlyAllProfileSafetySourceBuilder(ISSUE_ONLY_IN_STATELESS_ID).build()
752                     )
753                     .build()
754             )
755             .build()
756 
757     /** A [SafetyCenterConfig] containing only hidden sources. */
758     val hiddenOnlyConfig =
759         SafetyCenterConfig.Builder()
760             .addSafetySourcesGroup(
761                 safetySourcesGroupBuilder("some_collapsible_group")
762                     .addSafetySource(
763                         dynamicSafetySourceBuilder("some_hidden_source")
764                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
765                             .build()
766                     )
767                     .build()
768             )
769             .addSafetySourcesGroup(
770                 safetySourcesGroupBuilder("some_rigid_group")
771                     .setSummaryResId(Resources.ID_NULL)
772                     .addSafetySource(
773                         dynamicSafetySourceBuilder("another_hidden_source")
774                             .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
775                             .build()
776                     )
777                     .build()
778             )
779             .build()
780 
dynamicSafetySourcenull781     private fun dynamicSafetySource(id: String) = dynamicSafetySourceBuilder(id).build()
782 
783     fun dynamicSafetySourceBuilder(id: String) =
784         SafetySource.Builder(SAFETY_SOURCE_TYPE_DYNAMIC)
785             .setId(id)
786             .setPackageName(context.packageName)
787             .setTitleResId(android.R.string.ok)
788             .setSummaryResId(android.R.string.ok)
789             .setIntentAction(ACTION_TEST_ACTIVITY)
790             .setProfile(SafetySource.PROFILE_PRIMARY)
791             .setRefreshOnPageOpenAllowed(true)
792 
793     private fun dynamicAllProfileSafetySourceBuilder(id: String) =
794         dynamicSafetySourceBuilder(id)
795             .setProfile(SafetySource.PROFILE_ALL)
796             .setTitleForWorkResId(android.R.string.paste)
797             .apply {
798                 if (SdkLevel.isAtLeastV() && Flags.privateProfileTitleApi()) {
799                     setTitleForPrivateProfileResId(android.R.string.unknownName)
800                 }
801             }
802 
staticSafetySourcenull803     private fun staticSafetySource(id: String) = staticSafetySourceBuilder(id).build()
804 
805     private fun staticSafetySourceBuilder(id: String) =
806         SafetySource.Builder(SAFETY_SOURCE_TYPE_STATIC)
807             .setId(id)
808             .setTitleResId(android.R.string.ok)
809             .setSummaryResId(android.R.string.ok)
810             .setIntentAction(ACTION_TEST_ACTIVITY_EXPORTED)
811             .setProfile(SafetySource.PROFILE_PRIMARY)
812 
813     private fun staticAllProfileSafetySourceBuilder(id: String) =
814         staticSafetySourceBuilder(id)
815             .setProfile(SafetySource.PROFILE_ALL)
816             .setTitleForWorkResId(android.R.string.paste)
817             .apply {
818                 if (SdkLevel.isAtLeastV() && Flags.privateProfileTitleApi()) {
819                     setTitleForPrivateProfileResId(android.R.string.unknownName)
820                 }
821             }
822 
823     @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
issueOnlySafetySourceWithDuplicationInfonull824     private fun issueOnlySafetySourceWithDuplicationInfo(id: String, deduplicationGroup: String) =
825         issueOnlySafetySourceBuilder(id).setDeduplicationGroup(deduplicationGroup).build()
826 
827     private fun issueOnlySafetySource(id: String) = issueOnlySafetySourceBuilder(id).build()
828 
829     private fun issueOnlySafetySourceBuilder(id: String) =
830         SafetySource.Builder(SAFETY_SOURCE_TYPE_ISSUE_ONLY)
831             .setId(id)
832             .setPackageName(context.packageName)
833             .setProfile(SafetySource.PROFILE_PRIMARY)
834             .setRefreshOnPageOpenAllowed(true)
835 
836     private fun issueOnlyAllProfileSafetySourceBuilder(id: String) =
837         issueOnlySafetySourceBuilder(id).setProfile(SafetySource.PROFILE_ALL)
838 
839     private fun safetySourcesGroupBuilder(id: String) =
840         SafetySourcesGroup.Builder()
841             .setId(id)
842             .setTitleResId(android.R.string.ok)
843             .setSummaryResId(android.R.string.ok)
844 
845     private fun staticSafetySourcesGroupBuilder(id: String) =
846         SafetySourcesGroup.Builder().setId(id).setTitleResId(android.R.string.paste)
847 
848     fun singleSourceConfig(safetySource: SafetySource) =
849         SafetyCenterConfig.Builder()
850             .addSafetySourcesGroup(
851                 safetySourcesGroupBuilder(SINGLE_SOURCE_GROUP_ID)
852                     .addSafetySource(safetySource)
853                     .build()
854             )
855             .build()
856 
857     companion object {
858         /** ID of a source not used in any config. */
859         const val SAMPLE_SOURCE_ID = "test_sample_source_id"
860 
861         /** Activity action: Launches the [TestActivity] used to check redirects in tests. */
862         const val ACTION_TEST_ACTIVITY = "com.android.safetycenter.testing.action.TEST_ACTIVITY"
863 
864         /**
865          * Activity action: Launches the [TestActivity] used to check redirects in tests, but with
866          * an exported activity alias.
867          */
868         const val ACTION_TEST_ACTIVITY_EXPORTED =
869             "com.android.safetycenter.testing.action.TEST_ACTIVITY_EXPORTED"
870 
871         /**
872          * ID of the only source provided in [singleSourceConfig], [severityZeroConfig] and
873          * [noPageOpenConfig].
874          */
875         // LINT.IfChange(single_source_id)
876         const val SINGLE_SOURCE_ID = "test_single_source_id"
877         // LINT.ThenChange(/tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetyCenterInteractionLoggingHostTest.kt:single_source_id)
878 
879         /** ID of the only source provided in [singleSourceAllProfileConfig]. */
880         const val SINGLE_SOURCE_ALL_PROFILE_ID = "test_single_source_all_profile_id"
881 
882         /** ID of the only source provided in [issueOnlySourceAllProfileConfig]. */
883         const val ISSUE_ONLY_ALL_PROFILE_SOURCE_ID = "test_issue_only_all_profile_id"
884 
885         /**
886          * ID of the only [SafetySourcesGroup] provided by [singleSourceConfig],
887          * [severityZeroConfig] and [noPageOpenConfig].
888          */
889         const val SINGLE_SOURCE_GROUP_ID = "test_single_source_group_id"
890 
891         /**
892          * SHA256 hash of a package certificate.
893          *
894          * <p>This is a fake certificate, and can be used to test failure cases, or to test a list
895          * of certificates when only one match is required.
896          */
897         const val PACKAGE_CERT_HASH_FAKE = "feed12"
898 
899         /** An invalid SHA256 hash (not a byte string, not even number of chars). */
900         const val PACKAGE_CERT_HASH_INVALID = "0124ppl"
901 
902         /** ID of a source provided by [multipleSourcesConfig] and [summaryTestConfig]. */
903         const val SOURCE_ID_1 = "test_source_id_1"
904 
905         /** ID of a source provided by [multipleSourcesConfig] and [summaryTestConfig]. */
906         const val SOURCE_ID_2 = "test_source_id_2"
907 
908         /** ID of a source provided by [multipleSourcesConfig] and [summaryTestConfig]. */
909         const val SOURCE_ID_3 = "test_source_id_3"
910 
911         /** ID of a source provided by [summaryTestConfig]. */
912         const val SOURCE_ID_4 = "test_source_id_4"
913 
914         /** ID of a source provided by [summaryTestConfig]. */
915         const val SOURCE_ID_5 = "test_source_id_5"
916 
917         /** ID of a source provided by [summaryTestConfig]. */
918         const val SOURCE_ID_6 = "test_source_id_6"
919 
920         /** ID of a source provided by [summaryTestConfig]. */
921         const val SOURCE_ID_7 = "test_source_id_7"
922 
923         /**
924          * ID of a source provided by [privacySubpageConfig] and
925          * [privacySubpageWithoutDataSourcesConfig].
926          */
927         const val PRIVACY_SOURCE_ID_1 = "AndroidPermissionUsage"
928 
929         /**
930          * ID of a [SafetySourcesGroup] provided by [multipleSourcesConfig], containing two sources
931          * of ids [SOURCE_ID_1] and [SOURCE_ID_2].
932          */
933         const val MULTIPLE_SOURCES_GROUP_ID_1 = "test_multiple_sources_group_id_1"
934 
935         /**
936          * ID of a [SafetySourcesGroup] provided by [multipleSourcesConfig], containing a single
937          * source of id [SOURCE_ID_3].
938          */
939         const val MULTIPLE_SOURCES_GROUP_ID_2 = "test_multiple_sources_group_id_2"
940 
941         /**
942          * ID of a [SafetySourcesGroup] provided by [multipleSourcesConfig], containing two sources
943          * of ids [SOURCE_ID_4] and [SOURCE_ID_5].
944          */
945         const val MULTIPLE_SOURCES_GROUP_ID_3 = "test_multiple_sources_group_id_3"
946 
947         /**
948          * ID of a [SafetySourcesGroup] provided by [summaryTestGroupConfig], containing sources:
949          * [SOURCE_ID_1], [SOURCE_ID_2], [SOURCE_ID_3], [SOURCE_ID_4], [SOURCE_ID_5], [SOURCE_ID_6],
950          * [SOURCE_ID_7], [STATIC_IN_STATEFUL_ID].
951          */
952         const val SUMMARY_TEST_GROUP_ID = "summary_test_group_id"
953 
954         /**
955          * ID of a [SafetySourcesGroup] provided by [complexConfig], containing sources:
956          * [DYNAMIC_BAREBONE_ID], [DYNAMIC_ALL_OPTIONAL_ID], [DYNAMIC_DISABLED_ID],
957          * [DYNAMIC_HIDDEN_ID], [DYNAMIC_HIDDEN_WITH_SEARCH_ID], [DYNAMIC_OTHER_PACKAGE_ID]. And
958          * provided by [complexAllProfileConfig], containing sources: [DYNAMIC_BAREBONE_ID],
959          * [DYNAMIC_DISABLED_ID], [DYNAMIC_HIDDEN_ID].
960          */
961         const val DYNAMIC_GROUP_ID = "dynamic"
962 
963         /**
964          * ID of a [SafetySourcesGroup] provided by [complexConfig] and [complexAllProfileConfig],
965          * containing sources: [STATIC_BAREBONE_ID], [STATIC_ALL_OPTIONAL_ID].
966          */
967         const val STATIC_GROUP_ID = "static"
968 
969         /**
970          * ID of a [SafetySourcesGroup] provided by [complexConfig] and [complexAllProfileConfig],
971          * containing sources: [ISSUE_ONLY_BAREBONE_ID], [ISSUE_ONLY_ALL_OPTIONAL_ID].
972          */
973         const val ISSUE_ONLY_GROUP_ID = "issue_only"
974 
975         /**
976          * ID of a [SafetySourcesGroup] provided by [complexConfig], containing sources:
977          * [DYNAMIC_IN_STATEFUL_ID], [STATIC_IN_STATEFUL_ID].
978          */
979         const val MIXED_STATEFUL_GROUP_ID = "mixed_stateful"
980 
981         /**
982          * ID of a [SafetySourcesGroup] provided by [complexConfig] and [complexAllProfileConfig],
983          * containing sources: [DYNAMIC_IN_STATELESS_ID], [STATIC_IN_STATELESS_ID],
984          * [ISSUE_ONLY_IN_STATELESS_ID].
985          */
986         const val MIXED_STATELESS_GROUP_ID = "mixed_stateless"
987 
988         /**
989          * ID of a source provided by [complexConfig], [complexAllProfileConfig], and
990          * [androidLockScreenSourcesConfig], this is a dynamic, primary profile only, visible source
991          * for which only the required fields are set.
992          */
993         const val DYNAMIC_BAREBONE_ID = "dynamic_barebone"
994 
995         /**
996          * ID of a source provided by [complexConfig] and [singleSourceOtherPackageConfig], this is
997          * a dynamic, primary profile only, visible source belonging to the [OTHER_PACKAGE_NAME]
998          * package for which only the required fields are set.
999          */
1000         const val DYNAMIC_OTHER_PACKAGE_ID = "dynamic_other_package"
1001 
1002         /**
1003          * ID of a source provided by [complexConfig], this is a dynamic, primary profile only,
1004          * disabled by default source for which all the required and optional fields are set.
1005          * Notably, this includes the refresh on page open flag and a max severity level of
1006          * recommendation.
1007          */
1008         const val DYNAMIC_ALL_OPTIONAL_ID = "dynamic_all_optional"
1009 
1010         /**
1011          * ID of a source provided by [complexConfig], [complexAllProfileConfig], and
1012          * [androidLockScreenSourcesConfig], this is a dynamic, disabled by default source for which
1013          * only the required fields are set.
1014          */
1015         const val DYNAMIC_DISABLED_ID = "dynamic_disabled"
1016 
1017         /**
1018          * ID of a source provided by [complexConfig], [complexAllProfileConfig], and
1019          * [androidLockScreenSourcesConfig], this ism a dynamic, hidden by default source for which
1020          * only the required fields are set.
1021          */
1022         const val DYNAMIC_HIDDEN_ID = "dynamic_hidden"
1023 
1024         /**
1025          * ID of a source provided by [complexConfig], this is a dynamic, primary profile only,
1026          * hidden by default source for which all the required and optional fields are set.
1027          */
1028         const val DYNAMIC_HIDDEN_WITH_SEARCH_ID = "dynamic_hidden_with_search"
1029 
1030         /**
1031          * ID of a source provided by [complexConfig] and [complexAllProfileConfig], this is a
1032          * static, primary profile only source for which only the required fields are set.
1033          */
1034         const val STATIC_BAREBONE_ID = "static_barebone"
1035 
1036         /**
1037          * ID of a source provided by [complexConfig] and [complexAllProfileConfig], this is a
1038          * static source for which all the required and optional fields are set.
1039          */
1040         const val STATIC_ALL_OPTIONAL_ID = "static_all_optional"
1041 
1042         /**
1043          * ID of a source provided by [complexConfig] and [complexAllProfileConfig], this is an
1044          * issue-only, primary profile only source for which only the required fields are set.
1045          */
1046         const val ISSUE_ONLY_BAREBONE_ID = "issue_only_barebone"
1047 
1048         /**
1049          * ID of a source provided by [complexConfig] and [complexAllProfileConfig], this is an
1050          * issue-only source for which all the required and optional fields are set. Notably, this
1051          * includes the refresh on page open flag and a max severity level of recommendation.
1052          */
1053         const val ISSUE_ONLY_ALL_OPTIONAL_ID = "issue_only_all_optional"
1054 
1055         /**
1056          * ID of a source provided by [complexConfig], this is a generic, dynamic, primary profile
1057          * only, visible source.
1058          */
1059         const val DYNAMIC_IN_STATEFUL_ID = "dynamic_in_stateful"
1060 
1061         /**
1062          * ID of a source provided by [complexConfig] and [complexAllProfileConfig], this is a
1063          * generic, dynamic, visible source.
1064          */
1065         const val DYNAMIC_IN_STATELESS_ID = "dynamic_in_stateless"
1066 
1067         /**
1068          * ID of a source provided by [complexConfig] and [complexAllProfileConfig], this is an
1069          * issue-only source.
1070          */
1071         const val ISSUE_ONLY_IN_STATELESS_ID = "issue_only_in_stateless"
1072 
1073         /**
1074          * ID of a source provided by [complexConfig] and [summaryTestConfig], this is a generic,
1075          * static, primary profile only source.
1076          */
1077         const val STATIC_IN_STATEFUL_ID = "static_in_stateful"
1078 
1079         /**
1080          * ID of a source provided by [complexConfig] and [complexAllProfileConfig], this is a
1081          * generic, static source.
1082          */
1083         const val STATIC_IN_STATELESS_ID = "static_in_stateless"
1084 
1085         /** Package name for the [DYNAMIC_OTHER_PACKAGE_ID] source. */
1086         const val OTHER_PACKAGE_NAME = "other_package_name"
1087 
1088         private const val DEDUPLICATION_GROUP_1 = "deduplication_group_1"
1089         private const val DEDUPLICATION_GROUP_2 = "deduplication_group_2"
1090         private const val DEDUPLICATION_GROUP_3 = "deduplication_group_3"
1091 
1092         /**
1093          * ID of a [SafetySourcesGroup] provided by [settingsLockScreenSourceConfig] and
1094          * [androidLockScreenSourcesConfig], to replicate the lock screen sources group.
1095          */
1096         const val ANDROID_LOCK_SCREEN_SOURCES_GROUP_ID = "AndroidLockScreenSources"
1097 
1098         /**
1099          * ID of a [SafetySourcesGroup] provided by [privacySubpageConfig] and
1100          * [privacySubpageWithoutDataSourcesConfig], to replicate the privacy sources group.
1101          */
1102         const val ANDROID_PRIVACY_SOURCES_GROUP_ID = "AndroidPrivacySources"
1103 
1104         private const val INTENT_ACTION_NOT_RESOLVING = "there.is.no.way.this.resolves"
1105     }
1106 }
1107