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