summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp24
-rw-r--r--PermissionController/Android.bp7
-rw-r--r--PermissionController/AndroidManifest.xml22
-rw-r--r--PermissionController/res/drawable/coarse_off_dark.gifbin247280 -> 170063 bytes
-rw-r--r--PermissionController/res/drawable/coarse_off_light.gifbin198318 -> 127528 bytes
-rw-r--r--PermissionController/res/drawable/coarse_on_dark.gifbin248946 -> 196366 bytes
-rw-r--r--PermissionController/res/drawable/coarse_on_light.gifbin200690 -> 149193 bytes
-rw-r--r--PermissionController/res/drawable/fine_off_dark.gifbin246699 -> 178865 bytes
-rw-r--r--PermissionController/res/drawable/fine_off_light.gifbin152515 -> 110934 bytes
-rw-r--r--PermissionController/res/drawable/fine_on_dark.gifbin240398 -> 160541 bytes
-rw-r--r--PermissionController/res/drawable/fine_on_light.gifbin161732 -> 117548 bytes
-rw-r--r--PermissionController/res/layout/indicator_card.xml1
-rw-r--r--PermissionController/res/values-af/strings.xml15
-rw-r--r--PermissionController/res/values-am/strings.xml15
-rw-r--r--PermissionController/res/values-ar/strings.xml16
-rw-r--r--PermissionController/res/values-as/strings.xml15
-rw-r--r--PermissionController/res/values-az/strings.xml15
-rw-r--r--PermissionController/res/values-b+sr+Latn/strings.xml15
-rw-r--r--PermissionController/res/values-be/strings.xml15
-rw-r--r--PermissionController/res/values-bg/strings.xml15
-rw-r--r--PermissionController/res/values-bn/strings.xml15
-rw-r--r--PermissionController/res/values-bs/strings.xml15
-rw-r--r--PermissionController/res/values-ca/strings.xml15
-rw-r--r--PermissionController/res/values-cs/strings.xml15
-rw-r--r--PermissionController/res/values-da/strings.xml15
-rw-r--r--PermissionController/res/values-de/strings.xml15
-rw-r--r--PermissionController/res/values-el/strings.xml15
-rw-r--r--PermissionController/res/values-en-rAU/strings.xml13
-rw-r--r--PermissionController/res/values-en-rCA/strings.xml13
-rw-r--r--PermissionController/res/values-en-rGB/strings.xml13
-rw-r--r--PermissionController/res/values-en-rIN/strings.xml13
-rw-r--r--PermissionController/res/values-en-rXC/strings.xml13
-rw-r--r--PermissionController/res/values-es-rUS/strings.xml15
-rw-r--r--PermissionController/res/values-es/strings.xml17
-rw-r--r--PermissionController/res/values-et/strings.xml15
-rw-r--r--PermissionController/res/values-eu/strings.xml15
-rw-r--r--PermissionController/res/values-fa/strings.xml15
-rw-r--r--PermissionController/res/values-fi/strings.xml15
-rw-r--r--PermissionController/res/values-fr-rCA/strings.xml15
-rw-r--r--PermissionController/res/values-fr/strings.xml15
-rw-r--r--PermissionController/res/values-gl/strings.xml15
-rw-r--r--PermissionController/res/values-gu/strings.xml15
-rw-r--r--PermissionController/res/values-hi/strings.xml15
-rw-r--r--PermissionController/res/values-hr/strings.xml15
-rw-r--r--PermissionController/res/values-hu/strings.xml15
-rw-r--r--PermissionController/res/values-hy/strings.xml15
-rw-r--r--PermissionController/res/values-in/strings.xml15
-rw-r--r--PermissionController/res/values-is/strings.xml15
-rw-r--r--PermissionController/res/values-it/strings.xml41
-rw-r--r--PermissionController/res/values-iw/strings.xml15
-rw-r--r--PermissionController/res/values-ja/strings.xml13
-rw-r--r--PermissionController/res/values-ka/strings.xml15
-rw-r--r--PermissionController/res/values-kk/strings.xml15
-rw-r--r--PermissionController/res/values-km/strings.xml15
-rw-r--r--PermissionController/res/values-kn/strings.xml15
-rw-r--r--PermissionController/res/values-ko/strings.xml15
-rw-r--r--PermissionController/res/values-ky/strings.xml15
-rw-r--r--PermissionController/res/values-lo/strings.xml15
-rw-r--r--PermissionController/res/values-lt/strings.xml15
-rw-r--r--PermissionController/res/values-lv/strings.xml15
-rw-r--r--PermissionController/res/values-mk/strings.xml15
-rw-r--r--PermissionController/res/values-ml/strings.xml15
-rw-r--r--PermissionController/res/values-mn/strings.xml15
-rw-r--r--PermissionController/res/values-mr/strings.xml15
-rw-r--r--PermissionController/res/values-ms/strings.xml15
-rw-r--r--PermissionController/res/values-my/strings.xml15
-rw-r--r--PermissionController/res/values-nb/strings.xml15
-rw-r--r--PermissionController/res/values-ne/strings.xml15
-rw-r--r--PermissionController/res/values-nl/strings.xml17
-rw-r--r--PermissionController/res/values-or/strings.xml15
-rw-r--r--PermissionController/res/values-pa/strings.xml15
-rw-r--r--PermissionController/res/values-pl/strings.xml15
-rw-r--r--PermissionController/res/values-pt-rBR/strings.xml15
-rw-r--r--PermissionController/res/values-pt-rPT/strings.xml43
-rw-r--r--PermissionController/res/values-pt/strings.xml15
-rw-r--r--PermissionController/res/values-ro/strings.xml15
-rw-r--r--PermissionController/res/values-ru/strings.xml15
-rw-r--r--PermissionController/res/values-si/strings.xml15
-rw-r--r--PermissionController/res/values-sk/strings.xml15
-rw-r--r--PermissionController/res/values-sl/strings.xml15
-rw-r--r--PermissionController/res/values-sq/strings.xml15
-rw-r--r--PermissionController/res/values-sr/strings.xml15
-rw-r--r--PermissionController/res/values-sv/strings.xml15
-rw-r--r--PermissionController/res/values-sw/strings.xml15
-rw-r--r--PermissionController/res/values-ta/strings.xml16
-rw-r--r--PermissionController/res/values-te/strings.xml15
-rw-r--r--PermissionController/res/values-th/strings.xml15
-rw-r--r--PermissionController/res/values-tl/strings.xml13
-rw-r--r--PermissionController/res/values-tr/strings.xml15
-rw-r--r--PermissionController/res/values-uk/strings.xml15
-rw-r--r--PermissionController/res/values-ur/strings.xml16
-rw-r--r--PermissionController/res/values-uz/strings.xml15
-rw-r--r--PermissionController/res/values-vi/strings.xml15
-rw-r--r--PermissionController/res/values-zh-rCN/strings.xml15
-rw-r--r--PermissionController/res/values-zh-rHK/strings.xml15
-rw-r--r--PermissionController/res/values-zh-rTW/strings.xml15
-rw-r--r--PermissionController/res/values-zu/strings.xml15
-rw-r--r--PermissionController/res/values/strings.xml15
-rw-r--r--PermissionController/res/xml/roles.xml30
-rw-r--r--PermissionController/src/com/android/permissioncontroller/Constants.java12
-rw-r--r--PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt25
-rw-r--r--PermissionController/src/com/android/permissioncontroller/hibernation/HibernationPolicy.kt3
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/TEST_MAPPING12
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/model/AppPermissionGroup.java56
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java31
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceModel.kt22
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/v33/NotificationListenerCheck.kt (renamed from PermissionController/src/com/android/permissioncontroller/permission/service/NotificationListenerCheck.kt)268
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/v33/TEST_MAPPING15
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/AutoGrantPermissionsNotifier.java37
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java7
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java19
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.kt5
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionPreference.java28
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/SafetyCenterQsFragment.java123
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/SafetyCenterQsViewModel.kt (renamed from PermissionController/src/com/android/permissioncontroller/permission/ui/model/SafetyCenterViewModel.kt)69
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt12
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java24
-rw-r--r--PermissionController/src/com/android/permissioncontroller/privacysources/PrivacySource.kt49
-rw-r--r--PermissionController/src/com/android/permissioncontroller/privacysources/SafetyCenterReceiver.kt120
-rw-r--r--PermissionController/src/com/android/permissioncontroller/privacysources/package-info.java18
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/model/DevicePolicyManagementRoleBehavior.java39
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/model/HomeRoleBehavior.java21
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/model/Role.java27
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/model/RoleBehavior.java15
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java21
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/OWNERS1
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterDashboardFragment.java43
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyEntryPreference.java21
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/StaticSafetyEntryPreference.java24
-rw-r--r--PermissionController/tests/mocking/Android.bp1
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/auto/DrivingDecisionReminderServiceTest.kt286
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/permission/service/v33/NotificationListenerCheckInternalTest.kt (renamed from PermissionController/tests/mocking/src/com/android/permissioncontroller/permission/service/NotificationListenerCheckTest.kt)49
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/permission/ui/model/ReviewPermissionsViewModelTest.kt249
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/privacysources/SafetyCenterReceiverTest.kt189
-rw-r--r--SafetyCenter/Config/safety_center_config.xsd4
-rw-r--r--SafetyCenter/OWNERS5
-rw-r--r--SafetyCenter/Resources/AndroidManifest.xml4
-rw-r--r--SafetyCenter/Resources/res/values-af/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-am/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-as/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-az/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-b+sr+Latn/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-be/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-bg/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-bn/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-bs/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-ca/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-cs/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-da/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-de/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-el/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-en-rAU/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-en-rCA/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-en-rGB/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-en-rIN/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-en-rXC/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-es-rUS/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-es/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-et/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-eu/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-fa/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-fi/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-fr-rCA/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-fr/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-gl/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-gu/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-hi/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-hr/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-hu/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-hy/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-in/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-is/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-it/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-iw/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-ja/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-ka/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-kk/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-km/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-kn/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-ko/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-ky/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-lo/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-lt/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-lv/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-mk/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-ml/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-mn/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-mr/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-ms/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-my/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-nb/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-ne/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-nl/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-or/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-pa/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-pl/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-pt-rBR/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-pt-rPT/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-pt/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-ro/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-ru/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-si/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-sk/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-sl/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-sq/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-sr/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-sv/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-sw/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-te/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-th/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-tl/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-tr/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-uk/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-uz/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-vi/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-zh-rCN/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-zh-rHK/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-zh-rTW/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-zu/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/xml/safety_center_config.xml2
-rw-r--r--SafetyCenter/TEST_MAPPING7
-rw-r--r--apex_manifest.json2
-rw-r--r--framework-s/api/OWNERS1
-rw-r--r--framework-s/api/system-current.txt60
-rw-r--r--framework-s/java/android/safetycenter/ISafetyCenterManager.aidl21
-rw-r--r--framework-s/java/android/safetycenter/OWNERS1
-rw-r--r--framework-s/java/android/safetycenter/SafetyCenterData.java74
-rw-r--r--framework-s/java/android/safetycenter/SafetyCenterEntry.java281
-rw-r--r--framework-s/java/android/safetycenter/SafetyCenterEntryGroup.java104
-rw-r--r--framework-s/java/android/safetycenter/SafetyCenterEntryOrGroup.java64
-rw-r--r--framework-s/java/android/safetycenter/SafetyCenterErrorDetails.java40
-rw-r--r--framework-s/java/android/safetycenter/SafetyCenterFrameworkInitializer.java15
-rw-r--r--framework-s/java/android/safetycenter/SafetyCenterIssue.java278
-rw-r--r--framework-s/java/android/safetycenter/SafetyCenterManager.java300
-rw-r--r--framework-s/java/android/safetycenter/SafetyCenterStaticEntry.java122
-rw-r--r--framework-s/java/android/safetycenter/SafetyCenterStaticEntryGroup.java47
-rw-r--r--framework-s/java/android/safetycenter/SafetyCenterStatus.java135
-rw-r--r--framework-s/java/android/safetycenter/SafetyEvent.java122
-rw-r--r--framework-s/java/android/safetycenter/SafetySourceData.java183
-rw-r--r--framework-s/java/android/safetycenter/SafetySourceErrorDetails.java40
-rw-r--r--framework-s/java/android/safetycenter/SafetySourceIssue.java275
-rw-r--r--framework-s/java/android/safetycenter/SafetySourceStatus.java244
-rw-r--r--framework-s/java/android/safetycenter/config/BuilderUtils.java58
-rw-r--r--framework-s/java/android/safetycenter/config/ParseException.java3
-rw-r--r--framework-s/java/android/safetycenter/config/SafetyCenterConfig.java90
-rw-r--r--framework-s/java/android/safetycenter/config/SafetyCenterConfigParser.java155
-rw-r--r--framework-s/java/android/safetycenter/config/SafetySource.java327
-rw-r--r--framework-s/java/android/safetycenter/config/SafetySourcesGroup.java130
-rw-r--r--service/Android.bp8
-rw-r--r--service/java/com/android/role/RoleShellCommand.java9
-rw-r--r--service/java/com/android/safetycenter/OWNERS1
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterDataTracker.java115
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterRefreshManager.java33
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterService.java44
-rw-r--r--tests/cts/safetycenter/Android.bp7
-rw-r--r--tests/cts/safetycenter/AndroidManifest.xml2
-rw-r--r--tests/cts/safetycenter/AndroidTest.xml1
-rw-r--r--tests/cts/safetycenter/OWNERS2
-rw-r--r--tests/cts/safetycenter/TEST_MAPPING7
-rw-r--r--tests/cts/safetycenter/res/xml/config_static_safety_source_with_broadcast.xml16
-rw-r--r--tests/cts/safetycenter/res/xml/config_static_safety_source_with_notification.xml16
-rw-r--r--tests/cts/safetycenter/res/xml/config_valid.xml8
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/config/cts/ParserConfigInvalidTest.kt391
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/config/cts/ParserConfigValidTest.kt150
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/config/cts/SafetyCenterConfigTest.kt82
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/config/cts/SafetySourceTest.kt751
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/config/cts/SafetySourcesGroupTest.kt285
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterActivityTest.kt4
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterDataTest.kt235
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryGroupTest.kt243
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryOrGroupTest.kt113
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryTest.kt433
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterErrorDetailsTest.kt55
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterIssueTest.kt506
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt315
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterStaticEntryGroupTest.kt98
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterStaticEntryTest.kt136
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterStatusTest.kt210
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterUnsupportedTest.kt11
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetyEventTest.kt149
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceDataTest.kt377
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceErrorDetailsTest.kt47
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceIssueTest.kt1120
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceStatusTest.kt529
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/config/ParseExceptionTest.kt (renamed from tests/cts/safetycenter/src/android/safetycenter/config/cts/ParseExceptionTest.kt)5
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/config/ParserConfigInvalidTest.kt380
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/config/ParserConfigValidTest.kt180
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetyCenterConfigTest.kt77
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourceTest.kt557
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourcesGroupTest.kt241
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/config/XmlConfigTest.kt (renamed from tests/cts/safetycenter/src/android/safetycenter/cts/XmlConfigTest.kt)2
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/testing/Coroutines.kt37
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/testing/EqualsHashCodeToStringTester.kt84
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/testing/FakeExecutor.kt54
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/testing/Generic.java32
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/testing/SafetyCenterApisWithShellPermissions.kt185
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/testing/SafetyCenterFlags.kt (renamed from tests/cts/safetycenter/src/android/safetycenter/testing/SafetyCenterFlags.kt)4
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/testing/SafetySourceBroadcastReceiver.kt (renamed from tests/cts/safetycenter/src/android/safetycenter/testing/SafetySourceBroadcastReceiver.kt)18
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/testing/AnyTester.kt42
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/testing/ParcelableTester.kt25
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/testing/SafetyCenterApisWithShellPermissions.kt156
301 files changed, 9984 insertions, 7128 deletions
diff --git a/Android.bp b/Android.bp
index 52ea3abe3..188b314e1 100644
--- a/Android.bp
+++ b/Android.bp
@@ -86,6 +86,30 @@ bootclasspath_fragment {
additional_stubs: [
"android-non-updatable",
],
+
+ hidden_api: {
+ // The following packages contain classes from other modules on the
+ // bootclasspath. That means that the hidden API flags for this module
+ // has to explicitly list every single class this module provides in
+ // that package to differentiate them from the classes provided by other
+ // modules. That can include private classes that are not part of the
+ // API.
+ split_packages: [
+ "android.permission",
+ ],
+
+ // The following packages and all their subpackages currently only
+ // contain classes from this bootclasspath_fragment. Listing a package
+ // here won't prevent other bootclasspath modules from adding classes in
+ // any of those packages but it will prevent them from adding those
+ // classes into an API surface, e.g. public, system, etc.. Doing so will
+ // result in a build failure due to inconsistent flags.
+ package_prefixes: [
+ "android.app.role",
+ "android.safetycenter",
+ "com.android.permission",
+ ],
+ },
}
// Encapsulate the contributions made by the com.android.permission to the systemserverclasspath.
diff --git a/PermissionController/Android.bp b/PermissionController/Android.bp
index 950a52e21..d7bacd842 100644
--- a/PermissionController/Android.bp
+++ b/PermissionController/Android.bp
@@ -84,7 +84,12 @@ android_app {
srcs: [":permissioncontroller-sources"],
- libs: ["android.car-stubs"],
+ libs: [
+ "android.car-stubs",
+ // Soong fails to automatically add this dependency because all the
+ // *.kt sources are inside a filegroup.
+ "kotlin-annotations",
+ ],
static_libs: [
"iconloader",
diff --git a/PermissionController/AndroidManifest.xml b/PermissionController/AndroidManifest.xml
index 8dd4636b2..1dacc6dc7 100644
--- a/PermissionController/AndroidManifest.xml
+++ b/PermissionController/AndroidManifest.xml
@@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.android.permissioncontroller"
coreApp="true"
- android:versionCode="339999900"
+ android:versionCode="330000000"
android:versionName="33 system image"
>
@@ -80,7 +80,7 @@
</intent-filter>
</receiver>
- <receiver android:name="com.android.permissioncontroller.permission.service.NotificationListenerCheck$SetupPeriodicNotificationListenerCheck"
+ <receiver android:name="com.android.permissioncontroller.permission.service.v33.NotificationListenerCheck$SetupPeriodicNotificationListenerCheck"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
@@ -107,11 +107,9 @@
</intent-filter>
</receiver>
- <receiver android:name="com.android.permissioncontroller.permission.service.NotificationListenerCheck$NotificationDeleteHandler" />
+ <receiver android:name="com.android.permissioncontroller.permission.service.v33.NotificationListenerCheck$NotificationDeleteHandler" />
- <receiver android:name="com.android.permissioncontroller.permission.service.NotificationListenerCheck$NotificationClickHandler" />
-
- <receiver android:name="com.android.permissioncontroller.permission.service.NotificationListenerCheck$PackageResetHandler"
+ <receiver android:name="com.android.permissioncontroller.permission.service.v33.NotificationListenerCheck$PackageResetHandler"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_FULLY_REMOVED"/>
@@ -120,10 +118,20 @@
</intent-filter>
</receiver>
+ <receiver android:name="com.android.permissioncontroller.privacysources.SafetyCenterReceiver"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.safetycenter.action.SAFETY_CENTER_ENABLED_CHANGED"/>
+ <action android:name="android.safetycenter.action.REFRESH_SAFETY_SOURCES"/>
+ <action android:name="android.intent.action.BOOT_COMPLETED"/>
+ </intent-filter>
+ </receiver>
+
+
<service android:name="com.android.permissioncontroller.permission.service.LocationAccessCheck$LocationAccessCheckJobService"
android:permission="android.permission.BIND_JOB_SERVICE" />
- <service android:name="com.android.permissioncontroller.permission.service.NotificationListenerCheck$NotificationListenerCheckJobService"
+ <service android:name="com.android.permissioncontroller.permission.service.v33.NotificationListenerCheck$NotificationListenerCheckJobService"
android:permission="android.permission.BIND_JOB_SERVICE" />
<service android:name="com.android.permissioncontroller.hibernation.HibernationJobService"
diff --git a/PermissionController/res/drawable/coarse_off_dark.gif b/PermissionController/res/drawable/coarse_off_dark.gif
index f16f69ab8..09a7da18d 100644
--- a/PermissionController/res/drawable/coarse_off_dark.gif
+++ b/PermissionController/res/drawable/coarse_off_dark.gif
Binary files differ
diff --git a/PermissionController/res/drawable/coarse_off_light.gif b/PermissionController/res/drawable/coarse_off_light.gif
index b986037da..a5419cd91 100644
--- a/PermissionController/res/drawable/coarse_off_light.gif
+++ b/PermissionController/res/drawable/coarse_off_light.gif
Binary files differ
diff --git a/PermissionController/res/drawable/coarse_on_dark.gif b/PermissionController/res/drawable/coarse_on_dark.gif
index 3d762641f..a2ea07bd0 100644
--- a/PermissionController/res/drawable/coarse_on_dark.gif
+++ b/PermissionController/res/drawable/coarse_on_dark.gif
Binary files differ
diff --git a/PermissionController/res/drawable/coarse_on_light.gif b/PermissionController/res/drawable/coarse_on_light.gif
index 023b3791b..491edb612 100644
--- a/PermissionController/res/drawable/coarse_on_light.gif
+++ b/PermissionController/res/drawable/coarse_on_light.gif
Binary files differ
diff --git a/PermissionController/res/drawable/fine_off_dark.gif b/PermissionController/res/drawable/fine_off_dark.gif
index 3fdaa2cdc..560e38a34 100644
--- a/PermissionController/res/drawable/fine_off_dark.gif
+++ b/PermissionController/res/drawable/fine_off_dark.gif
Binary files differ
diff --git a/PermissionController/res/drawable/fine_off_light.gif b/PermissionController/res/drawable/fine_off_light.gif
index d1bc4efa8..5661b9270 100644
--- a/PermissionController/res/drawable/fine_off_light.gif
+++ b/PermissionController/res/drawable/fine_off_light.gif
Binary files differ
diff --git a/PermissionController/res/drawable/fine_on_dark.gif b/PermissionController/res/drawable/fine_on_dark.gif
index d22aa0832..aadf7821b 100644
--- a/PermissionController/res/drawable/fine_on_dark.gif
+++ b/PermissionController/res/drawable/fine_on_dark.gif
Binary files differ
diff --git a/PermissionController/res/drawable/fine_on_light.gif b/PermissionController/res/drawable/fine_on_light.gif
index 1668580b6..a592c6305 100644
--- a/PermissionController/res/drawable/fine_on_light.gif
+++ b/PermissionController/res/drawable/fine_on_light.gif
Binary files differ
diff --git a/PermissionController/res/layout/indicator_card.xml b/PermissionController/res/layout/indicator_card.xml
index 74c985709..d3a843622 100644
--- a/PermissionController/res/layout/indicator_card.xml
+++ b/PermissionController/res/layout/indicator_card.xml
@@ -18,6 +18,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
+ android:id="@+id/parent_card_view"
style="@style/IndicatorCardView">
<LinearLayout
android:orientation="vertical"
diff --git a/PermissionController/res/values-af/strings.xml b/PermissionController/res/values-af/strings.xml
index 2f7073708..957486b5a 100644
--- a/PermissionController/res/values-af/strings.xml
+++ b/PermissionController/res/values-af/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Sien al <xliff:g id="APP">%1$s</xliff:g> se toestemmings"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Sien alle programme met hierdie toestemming"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Wys Assistent-mikrofoongebruik"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Ongebruikte programinstellings"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Verwyder toestemmings as program nie gebruik word nie"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Verwyder toestemmings en maak spasie beskikbaar"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Om jou data te beskerm, sal toestemmings vir hierdie program verwyder word as die program \'n paar maande nie gebruik word nie."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Om jou data te beskerm, sal die volgende toestemmings verwyder word as dit vir \'n paar maande nie gebruik word nie: <xliff:g id="PERMS">%1$s</xliff:g>."</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Om jou data te beskerm, is toestemmings verwyder van programme wat jy \'n paar maande gelede laas gebruik het."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Terwyl jy bestuur het, het jy <xliff:g id="APP">%1$s</xliff:g> toegang gegee tot <xliff:g id="PERMISSION_1">%2$s</xliff:g> en <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Terwyl jy bestuur het, het jy <xliff:g id="COUNT">%1$d</xliff:g> toestemmings aan <xliff:g id="APP">%2$s</xliff:g> gegee"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Terwyl jy bestuur het, het jy <xliff:g id="APP_0">%1$s</xliff:g> en # ander program toegang gegee}other{Terwyl jy bestuur het, het jy <xliff:g id="APP_1">%1$s</xliff:g> en # ander programme toegang gegee}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Gaan na Instellings"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Sommige programme is \'n paar maande laas gebruik"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Toestemmings wat verwyder is"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Toestemmings is verwyder"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Gee &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot jou foonoproeprekords?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Laat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toe om foonoproepe te maak en te bestuur?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Gee &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot sensordata oor jou lewenstekens?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Dié program wil dalk deurentyd toegang tot sensordata oor jou lewenstekens hê, selfs wanneer jy nie die program gebruik nie. "<annotation id="link">"Laat toe in instellings."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Dié program wil dalk deurentyd toegang tot sensordata oor jou lewenstekens hê, selfs wanneer jy nie die program gebruik nie. "<annotation id="link">"Gaan na instellings"</annotation>" om hierdie verandering te maak."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Gee &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot die sensordata oor jou lewenstekens?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Dié program wil dalk deurentyd toegang tot sensordata oor jou lewenstekens hê, selfs wanneer jy nie die program gebruik nie. "<annotation id="link">"Laat toe in instellings."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Verander toegang tot sensordata oor jou lewenstekens vir &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783"><annotation id="link">"Gaan na instellings"</annotation>" om vir hierdie program toegang tot liggaamsensordata te gee, selfs wanneer jy nie die program gebruik nie."</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Gee &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; steeds toegang tot liggaamsensordata terwyl die program gebruik word?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Laat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toe om vir jou kennisgewings te stuur?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Laat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toe om steeds vir jou kennisgewings te stuur?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Beheerde toestemmings"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Verwyder kameratoestemming"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Verwyder mikrofoontoestemming"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Bestuur diens"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Bestuur toestemmings"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Word tans gebruik deur foonoproep"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Onlangs gebruik in foonoproep"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Word tans gebruik deur <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-am/strings.xml b/PermissionController/res/values-am/strings.xml
index a1a172b55..aeb282eba 100644
--- a/PermissionController/res/values-am/strings.xml
+++ b/PermissionController/res/values-am/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"ሁሉንም <xliff:g id="APP">%1$s</xliff:g> ፈቃዶች ይመልከቱ"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"ከዚህ መተግበሪያ ጋር ሁሉንም መተግበሪያዎች ይመልከቱ"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"የረዳት ማይክሮፎን አጠቃቀምን አሳይ"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"ስራ ላይ ያልዋሉ የመተግበሪያ ቅንብሮች"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"መተግበሪያ ጥቅም ላይ ካልዋለ ፈቃዶችን አስወግድ"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"ፈቃዶችን ያስወግዱ እና ቦታ ያስለቅቁ"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"ለእርስዎ ውሂብ ጥበቃ ለማድረግ፣ ለዚህ መተግበሪያ የተሰጡ ፈቃዶች መተግበሪያው ለጥቂት ወራት ጥቅም ላይ ካልዋለ ይህ መተግበሪያ ይወገዳል።"</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"የእርስዎን ውሂብ ለመጠበቅ፣ መተግበሪያው ለጥቂት ወራት ጥቅም ላይ ካልዋለ፣ የሚከተሉት ፈቃዶች ይወገዳሉ፦ <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"የእርስዎን ውሂብ ለመጠበቅ ሲባል ለጥቂት ወራት ካልተጠቀሙባቸው መተግበሪያዎች ላይ ፈቃዶች ተወግደዋል።"</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"እየነዱ ሳለ የ<xliff:g id="PERMISSION_1">%2$s</xliff:g> &amp; <xliff:g id="PERMISSION_2">%3$s</xliff:g> መዳረሻን ለ<xliff:g id="APP">%1$s</xliff:g> ሰጥተዋል"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"እየነዱ ሳለ <xliff:g id="COUNT">%1$d</xliff:g> ፈቃዶችን ለ<xliff:g id="APP">%2$s</xliff:g> ሰጥተዋል"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{እየነዱ ሳለ የ<xliff:g id="APP_0">%1$s</xliff:g> &amp; # ሌላ መተግበሪያ መዳረሻ ሰጥተዋል}one{እየነዱ ሳለ የ<xliff:g id="APP_1">%1$s</xliff:g> &amp; # ሌላ መተግበሪያ መዳረሻ ሰጥተዋል}other{እየነዱ ሳለ የ<xliff:g id="APP_1">%1$s</xliff:g> &amp; # ሌላ መተግበሪያ መዳረሻ ሰጥተዋል}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"ወደ ቅንብሮች ሂድ"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"አንዳንድ መተግበሪያዎች ለጥቂት ወሮች ስራ ላይ አልዋሉም።"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"ፈቃዶች የተወገዱባቸው"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"ፈቃዶች የተወገዱባቸው"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"የእርስዎን ስልክ የጥሪ ምዝግብ ማስታወሻዎች &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; እንዲደርስበት ይፈቀድ?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; የስልክ ጥሪዎችን እንዲያደርግ እና እንዲያቀናብር ይፈቀድለት?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; የሰውነትዎ መሠረታዊ ምልክቶች የዳሳሽ ውሂብ እንዲደርስ ይፈቀድለት?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"መተግበሪያውን በማይጠቀሙበት ጊዜም እንኳ ይህ መተግበሪያ ስለእርስዎ መሠረታዊ ምልክቶች የዳሳሽ ውሂብን ሁልጊዜ መድረስ ይፈልጋል። "<annotation id="link">"በቅንብሮች ውስጥ ይፍቀዱ።"</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"መተግበሪያውን በማይጠቀሙበት ጊዜም እንኳ ይህ መተግበሪያ የእርስዎን የመሠረታዊ ምልክቶች የዳሳሽ ውሂብን ሁልጊዜ መድረስ ይፈልጋል። ይህን ለውጥ ለማድረግ "<annotation id="link">"ወደ ቅንብሮች ይሂዱ።"</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; የሰውነትዎ መሠረታዊ ምልክቶች የዳሳሽ ውሂብ እንዲደርስ ይፈቀድለት?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"መተግበሪያውን በማይጠቀሙበት ጊዜም እንኳ ይህ መተግበሪያ ስለእርስዎ መሠረታዊ ምልክቶች ሁልጊዜ የዳሳሽ ውሂቡን መድረስ ሊፈልግ ይችላል። "<annotation id="link">"በቅንብሮች ውስጥ ይፍቀዱ።"</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"ለ&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ስለእርስዎ መሠረታዊ ምልክቶች የዳሳሽ ውሂብ መዳረሻ ይቀየር?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"መተግበሪያውን በማይጠቀሙበት ጊዜ እንኳን ይህ መተግበሪያ የሰውነት ዳሳሽ ውሂብን ሁልጊዜ እንዲደርስ ለመፍቀድ "<annotation id="link">"ወደ ቅንብሮች ይሂዱ።"</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"መተግበሪያ ስራ ላይ በሚውልበት ጊዜ የሰውነት ዳሳሽ ውሂብን እንዲደርስ ለ&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; መፍቀድ ይቀጥሉ?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ለእርስዎ ማሳወቂያዎች እንዲልክ ይፈቀድለት?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ለእርስዎ ማሳወቂያዎችን መላክ እንዲቀጥል ይፈቀድለት?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"ቁጥጥር የሚደረግባችድው ፈቃዶች"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"የካሜራ ፈቃድ ያስወግዱ"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"የማይክሮፎን ፈቃድ ያስወግዱ"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"አገልግሎት ያስተዳድሩ"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"ፈቃዶችን ያስተዳድሩ"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"በስልክ ጥሪ ስራ ላይ እየዋለ ነው"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"በቅርብ ጊዜ በስልክ ጥሪ ውስጥ ስራ ላይ ውሏል"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"በ<xliff:g id="APP_NAME">%1$s</xliff:g> ስራ ላይ እየዋለ ነው"</string>
diff --git a/PermissionController/res/values-ar/strings.xml b/PermissionController/res/values-ar/strings.xml
index b397a457c..5222d0af0 100644
--- a/PermissionController/res/values-ar/strings.xml
+++ b/PermissionController/res/values-ar/strings.xml
@@ -196,8 +196,14 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"الاطّلاع على جميع أذونات <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"الاطّلاع على جميع التطبيقات التي لديها هذا الإذن"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"‏عرض أذونات استخدام ميكروفون \"مساعد Google\""</string>
+ <!-- no translation found for unused_apps_category_title (2988455616845243901) -->
+ <skip />
<string name="auto_revoke_label" msgid="5068393642936571656">"إزالة الأذونات في حال عدم استخدام التطبيق"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"إزالة الأذونات وإخلاء مساحة"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"لحماية بياناتك، ستتم إزالة أذونات هذا التطبيق إذا لم يتم استخدامه لبضعة أشهر."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"لحماية بياناتك، إذا لم يتم استخدام التطبيق لبضعة أشهر، ستتم إزالة الأذونات التالية: <xliff:g id="PERMS">%1$s</xliff:g>."</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"لحماية بياناتك، تمت إزالة الأذونات من هذه التطبيقات التي لم تستخدمها منذ بضعة أشهر."</string>
@@ -264,8 +270,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"أثناء القيادة، منحت <xliff:g id="APP">%1$s</xliff:g> الإذن بالوصول إلى <xliff:g id="PERMISSION_1">%2$s</xliff:g> و<xliff:g id="PERMISSION_2">%3$s</xliff:g>."</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"أثناء القيادة، منحت <xliff:g id="COUNT">%1$d</xliff:g> إذن لتطبيق <xliff:g id="APP">%2$s</xliff:g>."</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{أثناء القيادة، منحت <xliff:g id="APP_0">%1$s</xliff:g> وتطبيق واحد آخر الإذن بالوصول.}zero{أثناء القيادة، منحت <xliff:g id="APP_1">%1$s</xliff:g> و# تطبيق آخر الإذن بالوصول.}two{أثناء القيادة، منحت <xliff:g id="APP_1">%1$s</xliff:g> وتطبيقين آخرين الإذن بالوصول.}few{أثناء القيادة، منحت <xliff:g id="APP_1">%1$s</xliff:g> و# تطبيقات أخرى الإذن بالوصول.}many{أثناء القيادة، منحت <xliff:g id="APP_1">%1$s</xliff:g> و# تطبيقًا آخر الإذن بالوصول.}other{أثناء القيادة، منحت <xliff:g id="APP_1">%1$s</xliff:g> و# تطبيق آخر الإذن بالوصول.}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"الانتقال إلى الإعدادات"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"لم يتم استخدام بعض التطبيقات منذ عدة أشهر"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"الأذونات التي تمت إزالتها"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"تمت إزالة الأذونات"</string>
@@ -468,10 +473,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى سجلّ مكالماتك الهاتفية؟"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"‏هل تريد السماح لـ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بإجراء المكالمات الهاتفية وإدارتها؟"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالدخول إلى بيانات المستشعر حول علاماتك الحيوية؟"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"يطلب هذا التطبيق الوصول إلى بيانات جهاز الاستشعار عن علاماتك الحيوية طوال الوقت، حتى عند عدم استخدامك للتطبيق. يمكنك "<annotation id="link">"السماح بذلك في الإعدادات."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"يطلب هذا التطبيق الوصول الدائم إلى بيانات جهاز الاستشعار المتعلّقة بالمؤشرات الحيوية، حتى في حال عدم استخدامك للتطبيق. لإجراء هذا التغيير، "<annotation id="link">"انتقِل إلى الإعدادات."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى بيانات جهاز الاستشعار عن علاماتك الحيوية؟"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"قد يحتاج هذا التطبيق إلى الوصول إلى بيانات جهاز الاستشعار عن علاماتك الحيوية طوال الوقت، حتى عند عدم استخدامك للتطبيق. يمكنك "<annotation id="link">"السماح بذلك في الإعدادات."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"‏هل تريد تغيير إذن وصول تطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; إلى بيانات جهاز الاستشعار عن العلامات الحيوية؟"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"للسماح لهذا التطبيق بالوصول باستمرار إلى بيانات أجهزة استشعار الجسم، وحتى في حال عدم استخدام التطبيق، "<annotation id="link">"يمكنك الانتقال إلى الإعدادات"</annotation>"."</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"‏هل تريد مواصلة السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; عند استخدامه بالوصول إلى بيانات أجهزة استشعار الجسم؟"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بإرسال إشعارات إليك؟"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بمواصلة إرسال إشعارات إليك؟"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"الأذونات خاضعة لتحكّم المشرف"</string>
@@ -509,6 +514,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"إزالة إذن الكاميرا"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"إزالة إذن الميكروفون"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"إدارة الخدمة"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"إدارة الأذونات"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"يتم الاستخدام في المكالمة الهاتفية"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"تم الاستخدام مؤخرًا في مكالمة هاتفية"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"يتم الاستخدام من قِبل <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-as/strings.xml b/PermissionController/res/values-as/strings.xml
index b263e11a4..735e46d22 100644
--- a/PermissionController/res/values-as/strings.xml
+++ b/PermissionController/res/values-as/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"আটাইবোৰ <xliff:g id="APP">%1$s</xliff:g> অনুমতি চাওক"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"এই অনুমতি থকা আটাইবোৰ এপ্ চাওক"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"সহায়ক মাইক্ৰ’ফ’নৰ ব্যৱহাৰ দেখুৱাওক"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"ব্যৱহাৰ নকৰা এপৰ ছেটিং"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"যদি এপ্‌টো ব্যৱহাৰ কৰা নাই অনুমতিসমূহ আঁতৰাওক"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"অনুমতি আঁতৰাওক আৰু ঠাই খালী কৰক"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"আপোনাৰ ডেটা সুৰক্ষিত কৰিবলৈ এই এপ্‌টো কেইমাহমান ব্যৱহাৰ নকৰিলে এইটোৰ বাবে থকা অনুমতিসমূহ আঁতৰোৱা হ\'ব।"</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"আপোনাৰ ডেটা সুৰক্ষিত কৰিবলৈ এই এপ্‌টো কেইমাহমান ব্যৱহাৰ নকৰিলে তলত উল্লেখ কৰা অনুমতিসমূহ আঁতৰোৱা হ\'ব: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"আপোনাৰ ডেটা সুৰক্ষিত কৰিবলৈ আপুনি কেইমাহমান ব্যৱহাৰ নকৰা এপ্‌সমূহৰ পৰা অনুমতিসমূহ আঁতৰোৱা হ\'ব।"</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"আপুনি গাড়ী চলাই থকাৰ সময়ত <xliff:g id="APP">%1$s</xliff:g>ক <xliff:g id="PERMISSION_1">%2$s</xliff:g> আৰু <xliff:g id="PERMISSION_2">%3$s</xliff:g>ৰ এক্সেছ দিছিল"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"আপুনি গাড়ী চলাই থকাৰ সময়ত <xliff:g id="APP">%2$s</xliff:g>ক <xliff:g id="COUNT">%1$d</xliff:g> টা অনুমতি দিছিল"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{আপুনি গাড়ী চলাই থকাৰ সময়ত <xliff:g id="APP_0">%1$s</xliff:g> আৰু # টা অন্য এপক এক্সেছ দিছিল}one{আপুনি গাড়ী চলাই থকাৰ সময়ত <xliff:g id="APP_1">%1$s</xliff:g> আৰু # টা অন্য এপক এক্সেছ দিছিল}other{আপুনি গাড়ী চলাই থকাৰ সময়ত <xliff:g id="APP_1">%1$s</xliff:g> আৰু # টা অন্য এপক এক্সেছ দিছিল}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"ছেটিঙলৈ যাওক"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"কিছুমান এপ্‌ কেইমাহমান ব্যৱহাৰ কৰা হোৱা নাই"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"আঁতৰোৱা অনুমতিসমূহ"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"অনুমতিসমূহ আঁতৰোৱা হৈছে"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ ফ\'ন কল লগ চাবলৈ অনুমতি দিবনে?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক ফ\'ন কল কৰিবলৈ আৰু পৰিচালনা কৰিবলৈ অনুমতি দিবনে?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ দেহৰ গুৰুত্বপূৰ্ণ অংগসমূহৰ অৱস্থাৰ বিষয়ে ছেন্সৰৰ ডেটা লাভ কৰিবলৈ অনুমতি দিবনে?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"এই এপ্‌টোৱে সকলো সময়তে আপোনাৰ দেহৰ গুৰুত্বপূৰ্ণ অংগৰ অৱস্থানৰ বিষয়ে ছেন্সৰৰ ডেটাৰ এক্সেছ বিচাৰে, আনকি আপুনি এপ্‌টো ব্যৱহাৰ কৰি নথকা সময়তো। "<annotation id="link">"ছেটিঙত অনুমতি দিয়ক।"</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"এই এপ্‌টোৱে সকলো সময়তে আপোনাৰ দেহৰ গুৰুত্বপূৰ্ণ অংগৰ বিষয়ে ছেন্সৰৰ ডেটাৰ এক্সেছ বিচাৰে, আনকি আপুনি এপ্‌টো ব্যৱহাৰ কৰি নথকাৰ সময়তো। এই সালসলনিটো কৰিবলৈ, "<annotation id="link">"ছেটিঙলৈ যাওক।"</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ দেহৰ গুৰুত্বপূৰ্ণ অংগসমূহৰ অৱস্থাৰ বিষয়ে ছেন্সৰৰ ডেটাৰ এক্সেছ পাবলৈ অনুমতি দিবনে?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"এই এপ্‌টোৱে সকলো সময়তে আপোনাৰ দেহৰ গুৰুত্বপূৰ্ণ অংগৰ বিষয়ে ছেন্সৰৰ ডেটাৰ এক্সেছ বিচাৰিব পাৰে, আনকি এপ্‌টো ব্যৱহাৰ কৰি নথকাৰ সময়তো। "<annotation id="link">"ছেটিঙত অনুমতি দিয়ক।"</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ৰ বাবে আপোনাৰ দেহৰ গুৰুত্বপূৰ্ণ অংগৰ অৱস্থানৰ বিষয়ে ছেন্সৰৰ ডেটা এক্সেছ কৰাটো সলনি কৰিবনে?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"এই এপ্‌টোক আপুনি ইয়াক ব্যৱহাৰ কৰি নথকাৰ সময়কে ধৰি সকলো সময়তে শৰীৰৰ ছেন্সৰৰ ডেটা এক্সেছ কৰিবলৈ দিবলৈ, "<annotation id="link">"ছেটিঙলৈ যাওক।"</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"এপ্‌টো ব্যৱহাৰ কৰি থকাৰ সময়ত &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক শৰীৰৰ ছেন্সৰৰ ডেটা এক্সেছ কৰিবলৈ অনুমতি দি থাকিবনে?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনালৈ জাননী পঠিয়াবলৈ অনুমতি দিবনে?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনালৈ জাননী পঠিয়াই থাকিবলৈ অনুমতি দিবনে?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"নিয়ন্ত্ৰিত অনুমতিসমূহ"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"কেমেৰাৰ অনুমতি আঁতৰাওক"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"মাইক্ৰ’ফ’নৰ অনুমতি আঁতৰাওক"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"সেৱা পৰিচালনা কৰক"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"অনুমতি পৰিচালনা কৰক"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"ফ’ন কলে ব্যৱহাৰ কৰি আছে"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"শেহতীয়াকৈ ফ’ন কলত ব্যৱহাৰ কৰা হৈছে"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ ব্যৱহাৰ কৰি আছে"</string>
diff --git a/PermissionController/res/values-az/strings.xml b/PermissionController/res/values-az/strings.xml
index bbccea756..311ed8cb8 100644
--- a/PermissionController/res/values-az/strings.xml
+++ b/PermissionController/res/values-az/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Bütün <xliff:g id="APP">%1$s</xliff:g> icazələrinə baxın"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Bu icazəyə sahib olan bütün tətbiqlərə baxın"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Assistent üçün mikrofon istifadəsini göstərin"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"İstifadə edilməyən tətbiq ayarları"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Tətbiq işlənməyəndə icazə ləğv edilsin"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"İcazələri silin və yer boşaldın"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Bir neçə ay istifadə etmədiyiniz tətbiqlərdən icazələr datanızın qorunması məqsədilə silinib."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Bir neçə ay istifadə etmədiyiniz tətbiqlərdən icazələr datanızın qorunması məqsədilə silinib: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Bir neçə ay istifadə etmədiyiniz tətbiqlərdən icazələr datanızın qorunması məqsədilə silinib."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Avtomobil sürərkən <xliff:g id="APP">%1$s</xliff:g> tətbiqinə <xliff:g id="PERMISSION_1">%2$s</xliff:g> və <xliff:g id="PERMISSION_2">%3$s</xliff:g> icazəsi vermisiniz"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Avtomobil sürərkən <xliff:g id="APP">%2$s</xliff:g> tətbiqinə <xliff:g id="COUNT">%1$d</xliff:g> icazə vermisiniz"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Avtomobil sürərkən <xliff:g id="APP_0">%1$s</xliff:g> tətbiqinə və digər # tətbiqə giriş icazəsi vermisiniz}other{Avtomobil sürərkən <xliff:g id="APP_1">%1$s</xliff:g> tətbiqinə və digər # tətbiqə giriş icazəsi vermisiniz}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Ayarlara keçin"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Bəzi tətbiqlər bir neçə aydır ki, istifadə edilməyib"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Silinmiş icazələr"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"İcazələr silinib"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə telefonun zəng qeydlərinə daxil olmaq icazəsi verilsin?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə telefon zəngləri etmək və onları idarə etmək icazəsi verilsin?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə həyati əlamətlər haqqında sensor dataya daxil olmaq icazəsi verilsin?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Bu tətbiq hər zaman, hətta ondan istifadə etmədiyiniz zaman belə sağlamlıq göstəriciləriniz haqqında sensor datasına giriş etmək istəyir. "<annotation id="link">"Ayarlarda icazə verin."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Bu tətbiq hər zaman, hətta ondan istifadə etmədiyiniz zaman belə sağlamlıq göstəriciləriniz haqqında sensor datasına giriş etmək istəyir. Bu dəyişikliyi etmək üçün "<annotation id="link">"ayarlara keçin"</annotation>"."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə sağlamlıq göstəriciləriniz haqqında sensor datasına giriş icazəsi verilsin?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Bu tətbiq hər zaman, hətta ondan istifadə etmədiyiniz zaman belə sağlamlıq göstəriciləriniz haqqında sensor datasına giriş etmək istəyə bilər. "<annotation id="link">"Ayarlarda icazə verin."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; üçün sağlamlıq göstəriciləriniz haqqında sensor datasına giriş dəyişdirilsin?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Tətbiqdən istifadə etmədiyiniz zaman belə, bu tətbiqin bədən sensoru datasına hər zaman giriş etməsinə icazə vermək üçün "<annotation id="link">"ayarlara keçin."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinin istifadə zamanı bədən sensoru datasına giriş etməsinə icazə verilməyə davam edilsin?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə sizə bildiriş göndərmək icazəsi verilsin?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə sizə yenə də bildiriş göndərmək icazəsi verilsin?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"İdarə edilən icazələr"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Kamera icazəsini silin"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Mikrofon icazəsini silin"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Xidməti idarə edin"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"İcazələri idarə edin"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Telefon zəngində istifadə edilir"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Bu yaxınlarda telefon zəngində istifadə edilib"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> tərəfindən istifadə edilir"</string>
diff --git a/PermissionController/res/values-b+sr+Latn/strings.xml b/PermissionController/res/values-b+sr+Latn/strings.xml
index 2c3c0c68a..08c4759e2 100644
--- a/PermissionController/res/values-b+sr+Latn/strings.xml
+++ b/PermissionController/res/values-b+sr+Latn/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Prikaži sve dozvole za: <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Prikaži sve aplikacije sa ovom dozvolom"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Prikaži kako Pomoćnik koristi mikrofon"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Podešavanja nekorišćenih aplikacija"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Ukloni dozvole ako se aplikacija ne koristi"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Ukloni dozvole i oslobodi prostor"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Radi zaštite podataka, dozvole za ovu aplikaciju se uklanjaju ako se aplikacija ne koristi par meseci."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Radi zaštite podataka, sledeće dozvole se uklanjaju ako se aplikacija ne koristi par meseci: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Radi zaštite podataka, dozvole su uklonjene iz aplikacija koje niste koristili par meseci."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Tokom vožnje ste dali aplikaciji <xliff:g id="APP">%1$s</xliff:g> pristup dozvolama <xliff:g id="PERMISSION_1">%2$s</xliff:g> i <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Tokom vožnje ste dali dozvole (<xliff:g id="COUNT">%1$d</xliff:g>) aplikaciji <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Tokom vožnje ste omogućili pristup za <xliff:g id="APP_0">%1$s</xliff:g> i još # drugu aplikaciju}one{Tokom vožnje ste omogućili pristup za <xliff:g id="APP_1">%1$s</xliff:g> i još # aplikaciju}few{Tokom vožnje ste omogućili pristup za <xliff:g id="APP_1">%1$s</xliff:g> i još # aplikacije}other{Tokom vožnje ste omogućili pristup za <xliff:g id="APP_1">%1$s</xliff:g> i još # aplikacija}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Idi u Podešavanja"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Neke aplikacije nisu korišćene par meseci"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Uklonjene dozvole"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Uklonjene dozvole"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Želite da dozvolite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristupa evidencijama poziva na telefonu?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Želite da dozvolite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; upućuje pozive i upravlja njima?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Želite da dozvolite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;pristupa podacima senzora o vitalnim funkcijama?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Ova aplikacija želi da pristupa podacima senzora o vitalnim funkcijama sve vreme, čak i kada ne koristite aplikaciju. "<annotation id="link">"Dozvolite u podešavanjima."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Ova aplikacija želi da sve vreme pristupa podacima senzora o vitalnim funkcijama, čak i kada ne koristite aplikaciju. Da biste obavili ovu izmenu, "<annotation id="link">"idite u podešavanja."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Želite da omogućite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristupa podacima senzora o vitalnim funkcijama?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Ova aplikacija možda želi da sve vreme pristupa podacima senzora o vitalnim funkcijama čak i kada ne koristite aplikaciju."<annotation id="link">"Dozvolite u podešavanjima."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Želite da promenite pristup podacima senzora o vitalnim funkcijama za &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Da biste dozvolili ovoj aplikaciji da sve vreme pristupa podacima senzora za telo, čak i kada ne koristite aplikaciju, "<annotation id="link">"idite u podešavanja."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Želite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; i dalje pristupa podacima senzora za telo dok se aplikacija koristi?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Želite da dozvolite da vam &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; šalje obaveštenja?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Želite da dozvolite da vam &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; i dalje šalje obaveštenja?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Kontrolisane dozvole"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Ukloni dozvolu za kameru"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Ukloni dozvolu za mikrofon"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Upravljajte uslugom"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Upravljajte dozvolama"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Koristi ga telefonski poziv"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Nedavno korišćeno u telefonskom pozivu"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Koristi aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-be/strings.xml b/PermissionController/res/values-be/strings.xml
index 585f39064..ec5fde726 100644
--- a/PermissionController/res/values-be/strings.xml
+++ b/PermissionController/res/values-be/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Паказаць усе дазволы праграмы \"<xliff:g id="APP">%1$s</xliff:g>\""</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Паказаць усе праграмы з гэтым дазволам"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Паказваць выкарыстанне мікрафона памочнікам"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Налады праграм, якія не выкарыстоўваліся"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Выдаляць дазволы, калі праграма не выкарыстоўваецца"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Выдаліць дазволы і вызваліць месца"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Калі праграма не выкарыстоўваецца на працягу некалькіх месяцаў, то ў мэтах абароны вашых даных з яе будуць выдалены дазволы."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Калі праграма не выкарыстоўваецца на працягу некалькіх месяцаў, у мэтах абароны вашых даных будуць выдалены наступныя дазволы: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"У мэтах абароны вашых даных выдалены дазволы для праграм, якія не выкарыстоўваліся некалькі месяцаў."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"У час язды вы далі праграме \"<xliff:g id="APP">%1$s</xliff:g>\" наступныя дазволы: <xliff:g id="PERMISSION_1">%2$s</xliff:g> і <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"У час язды вы далі праграме \"<xliff:g id="APP">%2$s</xliff:g>\" дазволы (<xliff:g id="COUNT">%1$d</xliff:g> шт.)"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{У час язды вы далі праграмам дазвол (\"<xliff:g id="APP_0">%1$s</xliff:g>\" і яшчэ # праграме)}one{У час язды вы далі праграмам дазвол (\"<xliff:g id="APP_1">%1$s</xliff:g>\" і яшчэ # праграме)}few{У час язды вы далі праграмам дазвол (\"<xliff:g id="APP_1">%1$s</xliff:g>\" і яшчэ # праграмам)}many{У час язды вы далі праграмам дазвол (\"<xliff:g id="APP_1">%1$s</xliff:g>\" і яшчэ # праграмам)}other{У час язды вы далі праграмам дазвол (\"<xliff:g id="APP_1">%1$s</xliff:g>\" і яшчэ # праграмы)}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Перайсці ў Налады"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Некаторыя праграмы не выкарыстоўваліся некалькі месяцаў"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Выдаленыя дазволы"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Дазволы выдалены"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да журналаў выклікаў вашага тэлефона?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; рабіць тэлефонныя выклікі і кіраваць імі?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да даных з датчыкаў пра вашы асноўныя фізіялагічныя паказчыкі?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Гэта праграма запытвае пастаянны доступ да даных датчыкаў з паказчыкамі вашага арганізма, навалі калі яна не выкарыстоўваецца. "<annotation id="link">"Дазволіць у наладах."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Гэта праграма запытвае пастаянны доступ да даных датчыкаў з паказчыкамі вашага арганізма, нават калі яна не выкарыстоўваецца. Каб змяніць дазвол, "<annotation id="link">"перайдзіце ў налады"</annotation>"."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да даных датчыкаў з паказчыкамі вашага арганізма?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Праграма можа запытваць пастаянны доступ да даных датчыкаў з паказчыкамі вашага арганізма, нават калі яна не выкарыстоўваецца. "<annotation id="link">"Дазволіць у наладах."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Змяніць для праграмы &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да даных датчыкаў з паказчыкамі вашага арганізма?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Каб дазволіць гэтай праграме мець пастаянны доступ да даных датчыкаў цела, нават калі яна не выкарыстоўваецца, "<annotation id="link">"перайдзіце ў налады."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Захаваць для праграмы \"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;” дазвол на доступ да даных датчыкаў цела ў час яе выкарыстання?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; адпраўляць вам апавяшчэнні?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; і далей адпраўляць апавяшчэнні?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Кіраваныя дазволы"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Выдаліць дазвол на доступ да камеры"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Выдаліць дазвол на доступ да мікрафона"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Кіраваць сэрвісамі"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Кіраваць дазволамі"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Выкарыстоўваецца падчас тэлефонных выклікаў"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Нядаўна выкарыстоўвалася ў час тэлефоннага выкліку"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Выкарыстоўваецца праграмай \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
diff --git a/PermissionController/res/values-bg/strings.xml b/PermissionController/res/values-bg/strings.xml
index f6ffcf7d2..0b3080c1f 100644
--- a/PermissionController/res/values-bg/strings.xml
+++ b/PermissionController/res/values-bg/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Преглед на всички разрешения за <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Преглед на всички приложения с това разрешение"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Показване на употребата на микрофона за Асистент"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Настройки за неизползваните приложения"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Премахване на разрешенията, ако приложението не се използва"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Премахване на разреш. и освоб. на място"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"За да защитим данните ви, разрешенията за това приложение ще бъдат премахнати, ако не го използвате няколко месеца."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"За да защитим данните ви, следните разрешения ще бъдат премахнати, ако не използвате приложението няколко месеца: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"За да защитим данните ви, премахнахме разрешенията за приложенията, които не сте използвали от няколко месеца."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"По време на шофиране предоставихте на <xliff:g id="APP">%1$s</xliff:g> достъп до <xliff:g id="PERMISSION_1">%2$s</xliff:g> и <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"По време на шофиране предоставихте <xliff:g id="COUNT">%1$d</xliff:g> разрешения на <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{По време на шофиране предоставихте достъп на <xliff:g id="APP_0">%1$s</xliff:g> и на още # приложение}other{По време на шофиране предоставихте достъп на <xliff:g id="APP_1">%1$s</xliff:g> и на още # приложения}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Към настройките"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Някои приложения не са използвани от няколко месеца"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Премахнати разрешения"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Разрешенията са премахнати"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да осъществява достъп до списъците с телефонните ви обаждания?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да извършва и управлява телефонни обаждания?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да осъществява достъп до данните от сензорите за жизнените ви показатели?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Това прил. иска достъп до данните от сензорите за жизнените ви показатели по всяко време – дори когато не го използвате. "<annotation id="link">"Разрешете от настройките."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Това приложение иска постоянен достъп до данните от сензорите за жизнените ви показатели – дори когато не го използвате. За да извършите тази промяна, "<annotation id="link">"отворете настройките"</annotation>"."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да осъществява достъп до данните от сензорите за жизнените ви показатели?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Това прил. може да иска достъп до данните от сензорите за жизн. ви показатели по всяко време – дори когато не го използвате. "<annotation id="link">"Разрешете от настройките."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Да се промени ли достъпът до данните от сензорите за жизнените ви показатели за &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"За да разрешите на това приложение да осъществява достъп до данните от сензорите за тяло по всяко време – дори когато не го използвате, "<annotation id="link">"отворете настройките."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Да се предоставя ли достъп на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; до данните от сензорите за тяло, докато приложението се използва?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да ви изпраща известия?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да продължи да ви изпраща известия?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Контролирани разрешения"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Премахване на разрешението за камерата"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Премахване на разрешението за микрофона"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Управление на услугата"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Управление на разрешенията"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Използва се от телефонно обаждане"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Наскоро използвано в телефонно обаждане"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Използва се от <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-bn/strings.xml b/PermissionController/res/values-bn/strings.xml
index 6bbc75bd1..28a5f3ef4 100644
--- a/PermissionController/res/values-bn/strings.xml
+++ b/PermissionController/res/values-bn/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"<xliff:g id="APP">%1$s</xliff:g>-এর ক্ষেত্রে দেওয়া সব অনুমতি দেখুন"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"যেসব অ্যাপের এই অনুমতি আছে সেগুলি দেখুন"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Assistant-এর মাইক্রোফোন ব্যবহার সম্পর্কিত ডেটা দেখুন"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"ব্যবহার করা হয়নি এমন অ্যাপ সেটিংস"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"অ্যাপ ব্যবহার করা না হলে সেটি থেকে অনুমতি প্রত্যাহার করে নিন"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"অনুমতি সরান এবং স্পেস খালি করুন"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"আপনার ডেটা সুরক্ষিত রাখতে এই অ্যাপ কয়েক মাস ব্যবহার করা না হলে, এটিকে দেওয়া অনুমতি প্রত্যাহার করে নেওয়া হবে।"</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"আপনার ডেটা সুরক্ষিত রাখতে অ্যাপটি কয়েক মাস ব্যবহার করা না হলে, এই অনুমতি প্রত্যাহার করে নেওয়া হবে: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"আপনার ডেটা সুরক্ষিত রাখতে যেসব অ্যাপ গত কয়েক মাস ব্যবহার করা হয়নি সেগুলি থেকে অনুমতি প্রত্যাহার করে নেওয়া হয়েছে।"</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"ড্রাইভ করার সময়, আপনি <xliff:g id="APP">%1$s</xliff:g>-কে <xliff:g id="PERMISSION_1">%2$s</xliff:g>এবং <xliff:g id="PERMISSION_2">%3$s</xliff:g>-এর অ্যাক্সেস দিয়েছেন"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"ড্রাইভ করার সময়, আপনি <xliff:g id="APP">%2$s</xliff:g>-কে <xliff:g id="COUNT">%1$d</xliff:g>টি অনুমতি দিয়েছেন"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{ড্রাইভ করার সময়, আপনি <xliff:g id="APP_0">%1$s</xliff:g> ও আরও #টি অ্যাপকে অ্যাক্সেস দিয়েছেন}one{ড্রাইভ করার সময়, আপনি <xliff:g id="APP_1">%1$s</xliff:g> ও আরও #টি অ্যাপকে অ্যাক্সেস দিয়েছেন}other{ড্রাইভ করার সময়, আপনি <xliff:g id="APP_1">%1$s</xliff:g> ও আরও #টি অ্যাপকে অ্যাক্সেস দিয়েছেন}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"\'সেটিংসে\' যান"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"কয়েক মাস ধরে কিছু অ্যাপ ব্যবহার করা হয়নি"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"যেসব অ্যাপের জন্য অনুমতি সরিয়ে নেওয়া হয়েছে"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"এই অ্যাপগুলির জন্য অনুমতি সরিয়ে নেওয়া হয়েছে"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে আপনার ফোন কল লগ অ্যাক্সেস করার অনুমতি দেবেন?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে কল করতে এবং কল পরিচালনা করতে দেবেন?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে সেন্সর থেকে আপনার ভাইটাল সাইনের ডেটা অ্যাক্সেস করতে দেবেন?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"অ্যাপ ব্যবহার না করলেও এই অ্যাপ আপনার বেঁচে থাকার গুরুত্বপূর্ণ লক্ষণ সম্পর্কিত সেন্সর ডেটা অ্যাক্সেসের অনুমতি চাইবে। "<annotation id="link">"সেটিংস থেকে অনুমতি দিন।"</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"এই অ্যাপ সবসময় শারীরবৃত্তীয় লক্ষণ সংক্রান্ত সেন্সর ডেটা অ্যাক্সেস করার অনুমতি চায়, এমনকী আপনি যখন অ্যাপটি ব্যবহার করছেন না, তখনও। এই পরিবর্তন চালু করতে, "<annotation id="link">"সেটিংসে যান।"</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে আপনার বেঁচে থাকার গুরুত্বপূর্ণ লক্ষণ সম্পর্কিত সেন্সর ডেটা অ্যাক্সেস করার অনুমতি দিতে চান?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"অ্যাপ ব্যবহার না করলেও এই অ্যাপ আপনার বেঁচে থাকার গুরুত্বপূর্ণ লক্ষণ সম্পর্কিত সেন্সর ডেটা অ্যাক্সেসের অনুমতি হয়ত চাইতে পারে। "<annotation id="link">"সেটিংস থেকে অনুমতি দিন।"</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"আপনার বেঁচে থাকার গুরুত্বপূর্ণ লক্ষণ সম্পর্কিত সেন্সর ডেটাতে &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-এর অ্যাক্সেসের অনুমতি পরিবর্তন করবেন?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"এই অ্যাপের ব্যবহার না করার সময়েও এটিকে বডি সেন্সর ডেটা অ্যাক্সেস করার অনুমতি দেওয়ার জন্য "<annotation id="link">"সেটিংসে যান।"</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"ব্যবহার করার সময় &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; অ্যাপকে বডি সেন্সর ডেটার অ্যাক্সেস দিয়ে রাখতে চান?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে বিজ্ঞপ্তি পাঠানোর অনুমতি দেবেন?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে বিজ্ঞপ্তি পাঠানো চালিয়ে যাওয়ার অনুমতি দেবেন?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"নিয়ন্ত্রিত অনুমতি"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"ক্যামেরার অনুমতি সরান"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"মাইক্রোফোনের অনুমতি সরান"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"পরিষেবা ম্যানেজ করুন"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"অনুমতি ম্যানেজ করুন"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"ফোন কলে ব্যবহার করা হচ্ছে"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"ফোন কলে ব্যবহার করা হয়েছে"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> অ্যাপে ব্যবহার করা হচ্ছে"</string>
diff --git a/PermissionController/res/values-bs/strings.xml b/PermissionController/res/values-bs/strings.xml
index 1f694d9c9..e900bd678 100644
--- a/PermissionController/res/values-bs/strings.xml
+++ b/PermissionController/res/values-bs/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Prikaži sva odobrenja aplikacije <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Prikaži sve aplikacije s ovim odobrenjem"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Prikaži korištenje mikrofona asistenta"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Postavke za nekorištene aplikacije"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Ukloni odobrenja ako se aplikacija ne koristi"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Ukloni odobrenja i oslobodi prostor"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Zbog zaštite vaših podataka, odobrenja za ovu aplikaciju će se ukloniti ako se ona ne bude koristila nekoliko mjeseci."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Radi zaštite vaših podataka, ako se aplikacija ne bude koristila nekoliko mjeseci, uklonit će se sljedeća odobrenja: <xliff:g id="PERMS">%1$s</xliff:g>."</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Zbog zaštite vaših podataka uklonjena su odobrenja iz aplikacija koje niste koristili nekoliko mjeseci."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Prilikom vožnje dali ste aplikaciji <xliff:g id="APP">%1$s</xliff:g> pristup odobrenjima <xliff:g id="PERMISSION_1">%2$s</xliff:g> i <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Prilikom vožnje dali ste aplikaciji <xliff:g id="APP">%2$s</xliff:g> <xliff:g id="COUNT">%1$d</xliff:g> odobrenja"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Prilikom vožnje dali ste pristup aplikaciji <xliff:g id="APP_0">%1$s</xliff:g> i još # aplikaciji}one{Prilikom vožnje dali ste pristup aplikaciji <xliff:g id="APP_1">%1$s</xliff:g> i još # aplikaciji}few{Prilikom vožnje dali ste pristup aplikaciji <xliff:g id="APP_1">%1$s</xliff:g> i još # aplikacije}other{Prilikom vožnje, dali ste pristup aplikaciji <xliff:g id="APP_1">%1$s</xliff:g> i još # aplikacija}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Idi u Postavke"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Neke aplikacije nisu korištene nekoliko mjeseci"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Uklonjena odobrenja"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Uklonjena odobrenja"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa zapisnicima poziva?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da upućuje pozive i upravlja njima?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristup senzornim podacima o vašim vitalnim znacima?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Ova aplikacija želi pristupiti podacima senzora o vašim vitalnim znakovima sve vrijeme, čak i kada je ne koristite. "<annotation id="link">"Dozvolite u postavkama."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Ova aplikacija želi pristupati podacima senzora o vašim vitalnim znakovima sve vrijeme, čak i kada je ne koristite. Da to promijenite, "<annotation id="link">"idite u postavke."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa podacima senzora o vašim vitalnim znakovima?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Ova aplikacija može tražiti pristup podacima senzora o vašim vitalnim znakovima sve vrijeme, čak i kada je ne koristite. "<annotation id="link">"Dozvolite u postavkama."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Promijeniti pristup podacima senzora o vašim vitalnim znakovima za aplikaciju &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Da dozvolite aplikaciji pristup podacima tjelesnih senzora sve vrijeme, čak i kada je ne koristite, "<annotation id="link">"idite u postavke."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Nastaviti dozvoljavati aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa podacima tjelesnih senzora dok se koristi?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da vam šalje obavještenja?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da vam nastavi slati obavještenja?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Kontrolirana odobrenja"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Uklonite odobrenje za kameru"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Uklonite odobrenje za mikrofon"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Upravljajte uslugom"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Upravljajte odobrenjima"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Koristi telefonski poziv"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Nedavno je korišteno u telefonskom pozivu"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Koristi aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-ca/strings.xml b/PermissionController/res/values-ca/strings.xml
index 008e2012c..fcc22fa5e 100644
--- a/PermissionController/res/values-ca/strings.xml
+++ b/PermissionController/res/values-ca/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Mostra tots els permisos per a <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Mostra totes les aplicacions que tenen aquest permís"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Mostra l\'ús del micròfon de l\'Assistent"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Configuració d\'apps no utilitzades"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Suprimeix els permisos si no s\'utilitza l\'aplicació"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Suprimeix els permisos i allibera espai"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Per protegir les teves dades, els permisos d\'aquesta aplicació se suprimiran si no la utilitzes durant uns mesos."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Si l\'aplicació no s\'utilitza durant uns mesos, se suprimiran els permisos següents per protegir les teves dades: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Per protegir les teves dades, s\'han suprimit els permisos de les aplicacions que no has utilitzat durant els darrers mesos."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Mentre conduïes, has concedit a <xliff:g id="APP">%1$s</xliff:g> accés a <xliff:g id="PERMISSION_1">%2$s</xliff:g> i <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Mentre conduïes, has concedit <xliff:g id="COUNT">%1$d</xliff:g> permisos a <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Mentre conduïes, has concedit accés a <xliff:g id="APP_0">%1$s</xliff:g> i a # aplicació més}other{Mentre conduïes, has concedit accés a <xliff:g id="APP_1">%1$s</xliff:g> i a # aplicacions més}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Ves a Configuració"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Durant els darrers mesos, no has utilitzat algunes aplicacions"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Permisos suprimits"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"S\'han suprimit els permisos"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; accedeixi als registres de trucades del telèfon?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; faci trucades telefòniques i les gestioni?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; accedeixi a les dades del sensor de constants vitals?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Aquesta aplicació vol accedir a les dades dels sensors sobre les constants vitals sempre, fins i tot quan no l\'utilitzis. "<annotation id="link">"Permet a la configuració."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Aquesta aplicació vol accedir a les dades del sensor sobre les constants vitals sempre, fins i tot quan no l\'utilitzis. Per fer aquest canvi, "<annotation id="link">"ves a la configuració"</annotation>"."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; accedeixi a les dades dels sensors sobre les constants vitals?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Aquesta aplicació vol accedir a les dades dels sensors sobre les constants vitals sempre, fins i tot quan no l\'utilitzis. "<annotation id="link">"Permet a la configuració"</annotation>"."</string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Vols canviar l\'accés de &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; a les dades dels sensors sobre les constants vitals?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Per permetre que l\'aplicació accedeixi sempre a les dades del sensor corporal, fins i tot quan no l\'utilitzis, "<annotation id="link">"ves a la configuració"</annotation>"."</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Vols continuar permetent que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; accedeixi a les dades del sensor corporal mentre s\'utilitza?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; t\'enviï notificacions?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; continuï enviant-te notificacions?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Permisos controlats"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Suprimeix el permís de la càmera"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Suprimeix el permís del micròfon"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Gestiona el servei"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Gestiona els permisos"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"En ús per una trucada"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Utilitzat recentment en una trucada"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"En ús per <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-cs/strings.xml b/PermissionController/res/values-cs/strings.xml
index 987c98304..279344c3b 100644
--- a/PermissionController/res/values-cs/strings.xml
+++ b/PermissionController/res/values-cs/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Zobrazit všechna oprávnění aplikace <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Zobrazit všechny aplikace s tímto oprávněním"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Zobrazit používání mikrofonu asistentem"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Nastavení nepoužívaných aplikací"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Odebrat oprávnění, pokud se aplikace nepoužívá"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Odebrat oprávnění a uvolnit místo"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Pokud tuto aplikaci několik měsíců nepoužijete, kvůli ochraně vašich dat jí budou oprávnění odebrána."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Pokud tuto aplikaci několik měsíců nepoužijete, budou jí kvůli ochraně vašich dat odebrána následující oprávnění: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Za účelem ochrany vašich dat byla odebrána oprávnění aplikacím, které jste několik měsíců nepoužili."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Při řízení jste aplikaci <xliff:g id="APP">%1$s</xliff:g> udělili přístup k: <xliff:g id="PERMISSION_1">%2$s</xliff:g> a <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Při řízení jste udělili <xliff:g id="COUNT">%1$d</xliff:g> oprávnění aplikaci <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Při řízení jste udělili přístup aplikaci <xliff:g id="APP_0">%1$s</xliff:g> a # další aplikaci}few{Při řízení jste udělili přístup aplikaci <xliff:g id="APP_1">%1$s</xliff:g> a # dalším aplikacím}many{Při řízení jste udělili přístup aplikaci <xliff:g id="APP_1">%1$s</xliff:g> a # další aplikace}other{Při řízení jste udělili přístup aplikaci <xliff:g id="APP_1">%1$s</xliff:g> a # dalším aplikacím}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Přejít do Nastavení"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Některé aplikace jste několik měsíců nepoužili"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Odebraná oprávnění"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Oprávnění byla odebrána"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; přístup k seznamu telefonních hovorů?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uskutečňovat a spravovat telefonní hovory?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; přístup k údajům ze snímačů vašich životních funkcí?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Aplikace požaduje přístup k datům ze senzorů vašich životních funkcí vždy, i když ji nebudete používat. "<annotation id="link">"Povolit to můžete v nastavení."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Aplikace požaduje přístup k datům ze senzorů vašich životních funkcí vždy, i když ji nebudete používat. Pokud tuto změnu chcete provést, "<annotation id="link">"přejděte do nastavení."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; přístup k datům ze senzorů vašich životních funkcí?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Tato aplikace může chtít přístup k datům ze senzorů vašich životních funkcí vždy, i když ji nebudete používat. "<annotation id="link">"Povolit to můžete v nastavení."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Změnit nastavení přístupu aplikace &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; k datům ze senzorů vašich životních funkcí?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Pokud chcete této aplikaci povolit trvalý přístup k datům z tělesných senzorů, i když aplikaci nepoužíváte, "<annotation id="link">"přejděte do nastavení"</annotation>"."</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Chcete, aby aplikace &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dál měla přístup k datům z tělesných senzorů během používání aplikace?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; odesílat oznámení?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; nadále odesílat oznámení?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Spravovaná oprávnění"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Odebrat oprávnění k fotoaparátu"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Odebrat oprávnění k mikrofonu"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Spravovat službu"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Správa oprávnění"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Právě používá telefonní hovor"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Nedávno použito při telefonním hovoru"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Právě používá aplikace <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-da/strings.xml b/PermissionController/res/values-da/strings.xml
index b99064621..4db9494b5 100644
--- a/PermissionController/res/values-da/strings.xml
+++ b/PermissionController/res/values-da/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Se alle tilladelser for <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Se alle apps med denne tilladelse"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Vis brug af Assistent-mikrofonen"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Ubrugte appindstillinger"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Fjern tilladelser, hvis appen ikke bruges"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Fjern tilladelser, og frigør plads"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Hvis appen ikke bliver brugt i et par måneder, fjernes tilladelser for appen for at beskytte dine data."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Hvis appen ikke bliver brugt i et par måneder, fjernes følgende tilladelser for at beskytte dine data: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Tilladelserne til apps, du ikke har brugt i et par måneder, er blevet fjernet for at beskytte dine data."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Under kørsel gav du <xliff:g id="APP">%1$s</xliff:g> adgang til <xliff:g id="PERMISSION_1">%2$s</xliff:g> og <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Under kørsel gav du <xliff:g id="APP">%2$s</xliff:g> <xliff:g id="COUNT">%1$d</xliff:g> tilladelser"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Under kørsel gav du <xliff:g id="APP_0">%1$s</xliff:g> og # anden app adgang}one{Under kørsel gav du <xliff:g id="APP_1">%1$s</xliff:g> og # anden app adgang}other{Under kørsel gav du <xliff:g id="APP_1">%1$s</xliff:g> og # andre apps adgang}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Gå til Indstillinger"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Nogle apps er ikke blevet brugt i et par måneder"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Fjernede tilladelser"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Tilladelser er fjernet"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; adgang til dine opkaldslister?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilladelse til at foretage og administrere telefonopkald?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; adgang til sensordata om dine livstegn?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Denne app vil gerne tilgå sensordataene om dine vitale værdier hele tiden, også når du ikke bruger appen. "<annotation id="link">"Giv tilladelse under Indstillinger."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Denne app anmoder om at tilgå sensordataene om dine vitale værdier hele tiden, også når du ikke bruger appen. Du kan foretage denne ændring ved at "<annotation id="link">"gå til indstillingerne."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; adgang til sensordataene om dine vitale værdier?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Denne app vil muligvis gerne tilgå sensordataene om dine vitale værdier hele tiden, også når du ikke bruger appen. "<annotation id="link">"Giv tilladelse under Indstillinger."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Vil du skifte adgangen til sensordataene om dine vitale værdier for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Du kan give denne app adgang til kropssensor hele tiden, selv når du ikke bruger appen, ved at "<annotation id="link">"gå til indstillingerne."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Vil du fortsætte med at give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; adgang til kropssensordata, mens appen er i brug?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilladelse til at sende dig notifikationer?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilladelse til at fortsætte med at sende dig notifikationer?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Administrerede tilladelser"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Fjern kameratilladelse"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Fjern mikrofontilladelse"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Administrer tjeneste"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Administrer tilladelser"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Anvendes i øjeblikket af telefonopkald"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Anvendt for nylig af telefonopkald"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Anvendes i øjeblikket af <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-de/strings.xml b/PermissionController/res/values-de/strings.xml
index c9fcbb0d6..88632da72 100644
--- a/PermissionController/res/values-de/strings.xml
+++ b/PermissionController/res/values-de/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Alle Berechtigungen der App „<xliff:g id="APP">%1$s</xliff:g>“ anzeigen"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Alle Apps mit dieser Berechtigung anzeigen"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Nutzung der Berechtigung \"Mikrofon\" für Assistant anzeigen"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Nicht verwendete App-Einstellungen"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Berechtigungen entfernen, wenn die App nicht verwendet wird"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Berechtigungen löschen und Speicherplatz freigeben"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Zum Schutz deiner Daten werden dieser App die Berechtigungen entzogen, wenn du sie einige Monate nicht verwendest."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Zum Schutz deiner Daten werden dieser App die folgenden Berechtigungen entzogen, wenn du sie einige Monate nicht verwendest: <xliff:g id="PERMS">%1$s</xliff:g>."</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Zum Schutz deiner Daten wurden Apps, die du einige Monate nicht verwendet hast, Berechtigungen entzogen."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Während der Fahrt hast du <xliff:g id="APP">%1$s</xliff:g> Zugriff auf die Berechtigungen „<xliff:g id="PERMISSION_1">%2$s</xliff:g>“ &amp; „<xliff:g id="PERMISSION_2">%3$s</xliff:g>“ gewährt"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Während der Fahrt hast du <xliff:g id="APP">%2$s</xliff:g> <xliff:g id="COUNT">%1$d</xliff:g> Berechtigungen gewährt"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Während der Fahrt hast du <xliff:g id="APP_0">%1$s</xliff:g> &amp; # anderen App Zugriff gewährt}other{Während der Fahrt hast du <xliff:g id="APP_1">%1$s</xliff:g> &amp; # anderen Apps Zugriff gewährt}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Zu den Einstellungen"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Einige Apps wurden seit mehreren Monaten nicht genutzt"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Entfernte Berechtigungen"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Berechtigungen entfernt"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, auf deine Anrufliste zuzugreifen?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, Anrufe zu starten und zu verwalten?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, auf Sensordaten zu deinen Vitalfunktionen zuzugreifen?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Die App möchte auf die Sensordaten zu deinen Vitalfunktionen zugreifen, auch wenn du sie nicht verwendest. "<annotation id="link">"Du kannst das in den Einstellungen zulassen."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Die App möchte jederzeit auf die Sensordaten zu deinen Vitalfunktionen zugreifen, auch wenn du sie nicht verwendest. Du kannst das "<annotation id="link">"in den Einstellungen ändern"</annotation>"."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, auf Sensordaten zu deinen Vitalfunktionen zuzugreifen?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Diese App möchte ggf. auf die Sensordaten zugreifen, auch wenn du die App nicht verwendest. "<annotation id="link">"Du kannst das in den Einstellungen zulassen."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Zugriff auf Sensordaten zu deinen Vitalfunktionen für &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ändern?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Wenn diese App dauerhaft auf Daten des Körpersensors zugreifen können soll, auch dann, wenn sie nicht verwendet wird, "<annotation id="link">"gehe zu den Einstellungen"</annotation>"."</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; Zugriff auf Körpersensordaten bei Benutzung weiter erlauben?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, dir Benachrichtigungen zu senden?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Möchtest du zulassen, dass &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dir weiterhin Benachrichtigungen sendet?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Erteilte Berechtigungen"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Kameraberechtigung entfernen"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Mikrofonberechtigung entfernen"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Dienst verwalten"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Berechtigungen verwalten"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Im Telefonanruf verwendet"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Kürzlich in einem Telefonanruf verwendet"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Von <xliff:g id="APP_NAME">%1$s</xliff:g> verwendet"</string>
diff --git a/PermissionController/res/values-el/strings.xml b/PermissionController/res/values-el/strings.xml
index 7e8794d7b..d987e1bef 100644
--- a/PermissionController/res/values-el/strings.xml
+++ b/PermissionController/res/values-el/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Εμφάνιση όλων των αδειών της εφαρμογής <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Εμφάνιση όλων των εφαρμογών με αυτήν την άδεια"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Εμφάνιση χρήσης μικροφώνου βοηθού"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Ρυθμίσεις μη χρησιμοποιούμενων εφαρμογών"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Καταργήστε τις άδειες, εάν η εφαρμογή δεν χρησιμοποιείται."</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Κατάργηση αδειών και απελευθέρωση χώρου"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Για την προστασία των δεδομένων σας, οι άδειες για αυτήν την εφαρμογή θα καταργηθούν εάν η εφαρμογή δεν χρησιμοποιηθεί για μερικούς μήνες."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Για την προστασία των δεδομένων σας, εάν δεν έχει χρησιμοποιηθεί η εφαρμογή για μερικούς μήνες, οι παρακάτω άδειες θα καταργηθούν: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Για την προστασία των δεδομένων σας, έχουν καταργηθεί οι άδειες εφαρμογών που δεν έχετε χρησιμοποιήσει κατά τους τελευταίους μήνες."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Ενώ οδηγούσατε, εκχωρήσατε στην εφαρμογή <xliff:g id="APP">%1$s</xliff:g> πρόσβαση στις άδειες <xliff:g id="PERMISSION_1">%2$s</xliff:g> και <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Ενώ οδηγούσατε, εκχωρήσατε <xliff:g id="COUNT">%1$d</xliff:g> άδειες στην εφαρμογή <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Ενώ οδηγούσατε, εκχωρήσατε πρόσβαση στην εφαρμογή <xliff:g id="APP_0">%1$s</xliff:g> και σε # άλλη εφαρμογή}other{Ενώ οδηγούσατε, εκχωρήσατε πρόσβαση στην εφαρμογή <xliff:g id="APP_1">%1$s</xliff:g> και σε # άλλες εφαρμογές}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Μετάβαση στις Ρυθμίσεις"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Ορισμένες εφαρμογές δεν έχουν χρησιμοποιηθεί τους τελευταίους μήνες."</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Άδειες που καταργήθηκαν"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Άδειες που καταργήθηκαν"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Να επιτρέπεται στην εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να έχει πρόσβαση στα αρχεία καταγραφής τηλεφωνικών κλήσεών σας;"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Να επιτρέπεται στην εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; η πραγματοποίηση και η διαχείριση τηλεφωνικών κλήσεων;"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Να επιτρέπεται στην εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να έχει πρόσβαση στα δεδομένα αισθητήρα σχετικά με τις ζωτικές ενδείξεις σας;"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Αυτή η εφαρμογή θέλει πρόσβαση στα δεδομένα αισθητήρα για τις ζωτικές σας ενδείξεις, ακόμη και όταν δεν τη χρησιμοποιείτε. "<annotation id="link">"Αποδοχή στις ρυθμίσεις."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Αυτή η εφαρμογή θέλει πρόσβαση στα δεδομένα αισθητήρα για τις ζωτικές σας ενδείξεις, ακόμη και όταν δεν τη χρησιμοποιείτε. Για να κάνετε αυτήν την αλλαγή, "<annotation id="link">"μεταβείτε στις ρυθμίσεις."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Να επιτρέπεται στην εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; η πρόσβαση σε δεδομένα αισθητήρα σχετικά με τις ζωτικές ενδείξεις σας;"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Αυτή η εφαρμογή θέλει πρόσβαση στα δεδομένα αισθητήρα για ζωτικές ενδείξεις συνεχώς, ακόμη και όταν δεν τη χρησιμοποιείτε. "<annotation id="link">"Αποδοχή στις ρυθμίσεις."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Αλλαγή πρόσβασης σε δεδομένα αισθητήρα σχετικά με τις ζωτικές σας ενδείξεις για την εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;;"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Για να επιτρέψετε σε αυτήν την εφαρμογή να αποκτά πρόσβαση σε δεδομένα αισθητήρων σώματος οποιαδήποτε στιγμή, ακόμα και όταν δεν χρησιμοποιείτε την εφαρμογή, "<annotation id="link">"μεταβείτε στις ρυθμίσεις."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Να συνεχίσει να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; η πρόσβαση σε δεδομένα αισθητήρων σώματος ενώ χρησιμοποιείται;"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Επιτρέπετε στην εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να σας στέλνει ειδοποιήσεις;"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Επιτρέπετε στην εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να συνεχίσει να σας στέλνει ειδοποιήσεις;"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Ελεγχόμενες άδειες"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Κατάργηση άδειας για την κάμερα"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Κατάργηση άδειας για το μικρόφωνο"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Διαχείριση υπηρεσίας"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Διαχείριση αδειών"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Χρησιμοποιείται από την τηλεφωνική κλήση"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Χρησιμοποιήθηκε πρόσφατα στην τηλεφωνική κλήση"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Χρησιμοποιείται από την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-en-rAU/strings.xml b/PermissionController/res/values-en-rAU/strings.xml
index a4b997237..a5023010a 100644
--- a/PermissionController/res/values-en-rAU/strings.xml
+++ b/PermissionController/res/values-en-rAU/strings.xml
@@ -196,8 +196,11 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"See all <xliff:g id="APP">%1$s</xliff:g> permissions"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"See all apps with this permission"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Show Assistant microphone usage"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Unused app settings"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Remove permissions if app isn’t used"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Remove permissions and free up space"</string>
+ <string name="unused_apps_label_v2" msgid="7058776770056517980">"Pause app activity if unused"</string>
+ <string name="unused_apps_summary" msgid="8839466950318403115">"Remove permissions, delete temporary files and stop notifications"</string>
<string name="auto_revoke_summary" msgid="5867548789805911683">"To protect your data, permissions for this app will be removed if the app is unused for a few months."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"To protect your data, if the app is unused for a few months, the following permissions will be removed: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"To protect your data, permissions have been removed from apps that you haven’t used in a few months."</string>
@@ -264,8 +267,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"While driving, you gave <xliff:g id="APP">%1$s</xliff:g> access to <xliff:g id="PERMISSION_1">%2$s</xliff:g> &amp; <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"While driving, you granted <xliff:g id="COUNT">%1$d</xliff:g> permissions to <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{While driving, you gave <xliff:g id="APP_0">%1$s</xliff:g> &amp; # other app access}other{While driving, you gave <xliff:g id="APP_1">%1$s</xliff:g> &amp; # other apps access}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Go to Settings"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Some apps haven’t been used for a few months"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Removed permissions"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Permissions removed"</string>
@@ -468,10 +470,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your phone call logs?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to make and manage phone calls?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access sensor data about your vital signs?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"This app wants to access sensor data about your vital signs all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"This app wants to access sensor data about your vital signs all the time, even when you’re not using the app. To make this change, "<annotation id="link">"go to Settings."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access the sensor data about your vital signs?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"This app may want to access the sensor data about your vital signs all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Change access to sensor data about your vital signs for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"To let this app access body sensor data all the time, even when you\'re not using the app, "<annotation id="link">"go to settings."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Keep allowing &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access body sensor data while the app is in use?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to send you notifications?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to continue sending you notifications?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Controlled permissions"</string>
@@ -509,6 +511,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Remove camera permission"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Remove microphone permission"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Manage service"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Manage permissions"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Being used by phone call"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Recently used in phone call"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Being used by <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-en-rCA/strings.xml b/PermissionController/res/values-en-rCA/strings.xml
index a4b997237..a5023010a 100644
--- a/PermissionController/res/values-en-rCA/strings.xml
+++ b/PermissionController/res/values-en-rCA/strings.xml
@@ -196,8 +196,11 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"See all <xliff:g id="APP">%1$s</xliff:g> permissions"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"See all apps with this permission"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Show Assistant microphone usage"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Unused app settings"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Remove permissions if app isn’t used"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Remove permissions and free up space"</string>
+ <string name="unused_apps_label_v2" msgid="7058776770056517980">"Pause app activity if unused"</string>
+ <string name="unused_apps_summary" msgid="8839466950318403115">"Remove permissions, delete temporary files and stop notifications"</string>
<string name="auto_revoke_summary" msgid="5867548789805911683">"To protect your data, permissions for this app will be removed if the app is unused for a few months."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"To protect your data, if the app is unused for a few months, the following permissions will be removed: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"To protect your data, permissions have been removed from apps that you haven’t used in a few months."</string>
@@ -264,8 +267,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"While driving, you gave <xliff:g id="APP">%1$s</xliff:g> access to <xliff:g id="PERMISSION_1">%2$s</xliff:g> &amp; <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"While driving, you granted <xliff:g id="COUNT">%1$d</xliff:g> permissions to <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{While driving, you gave <xliff:g id="APP_0">%1$s</xliff:g> &amp; # other app access}other{While driving, you gave <xliff:g id="APP_1">%1$s</xliff:g> &amp; # other apps access}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Go to Settings"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Some apps haven’t been used for a few months"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Removed permissions"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Permissions removed"</string>
@@ -468,10 +470,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your phone call logs?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to make and manage phone calls?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access sensor data about your vital signs?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"This app wants to access sensor data about your vital signs all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"This app wants to access sensor data about your vital signs all the time, even when you’re not using the app. To make this change, "<annotation id="link">"go to Settings."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access the sensor data about your vital signs?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"This app may want to access the sensor data about your vital signs all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Change access to sensor data about your vital signs for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"To let this app access body sensor data all the time, even when you\'re not using the app, "<annotation id="link">"go to settings."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Keep allowing &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access body sensor data while the app is in use?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to send you notifications?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to continue sending you notifications?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Controlled permissions"</string>
@@ -509,6 +511,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Remove camera permission"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Remove microphone permission"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Manage service"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Manage permissions"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Being used by phone call"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Recently used in phone call"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Being used by <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-en-rGB/strings.xml b/PermissionController/res/values-en-rGB/strings.xml
index 7bd4e0b0a..7705d1bd8 100644
--- a/PermissionController/res/values-en-rGB/strings.xml
+++ b/PermissionController/res/values-en-rGB/strings.xml
@@ -196,8 +196,11 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"See all <xliff:g id="APP">%1$s</xliff:g> permissions"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"See all apps with this permission"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Show Assistant microphone usage"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Unused app settings"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Remove permissions if app isn’t used"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Remove permissions and free up space"</string>
+ <string name="unused_apps_label_v2" msgid="7058776770056517980">"Pause app activity if unused"</string>
+ <string name="unused_apps_summary" msgid="8839466950318403115">"Remove permissions, delete temporary files and stop notifications"</string>
<string name="auto_revoke_summary" msgid="5867548789805911683">"To protect your data, permissions for this app will be removed if the app is unused for a few months."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"To protect your data, if the app is unused for a few months, the following permissions will be removed: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"To protect your data, permissions have been removed from apps that you haven’t used in a few months."</string>
@@ -264,8 +267,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"While driving, you gave <xliff:g id="APP">%1$s</xliff:g> access to <xliff:g id="PERMISSION_1">%2$s</xliff:g> &amp; <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"While driving, you granted <xliff:g id="COUNT">%1$d</xliff:g> permissions to <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{While driving, you gave <xliff:g id="APP_0">%1$s</xliff:g> &amp; # other app access}other{While driving, you gave <xliff:g id="APP_1">%1$s</xliff:g> &amp; # other apps access}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Go to Settings"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Some apps haven’t been used for a few months"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Removed permissions"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Permissions removed"</string>
@@ -468,10 +470,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your phone call logs?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to make and manage phone calls?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access sensor data about your vital signs?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"This app wants to access sensor data about your vital signs all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"This app wants to access sensor data about your vital signs all the time, even when you’re not using the app. To make this change, "<annotation id="link">"go to Settings."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access the sensor data about your vital signs?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"This app may want to access the sensor data about your vital signs all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Change access to sensor data about your vital signs for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"To let this app access body sensor data all the time, even when you\'re not using the app, "<annotation id="link">"go to settings."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Keep allowing &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access body sensor data while the app is in use?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to send you notifications?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to continue sending you notifications?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Controlled permissions"</string>
@@ -509,6 +511,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Remove camera permission"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Remove microphone permission"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Manage service"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Manage permissions"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Being used by phone call"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Recently used in phone call"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Being used by <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-en-rIN/strings.xml b/PermissionController/res/values-en-rIN/strings.xml
index 7bd4e0b0a..7705d1bd8 100644
--- a/PermissionController/res/values-en-rIN/strings.xml
+++ b/PermissionController/res/values-en-rIN/strings.xml
@@ -196,8 +196,11 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"See all <xliff:g id="APP">%1$s</xliff:g> permissions"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"See all apps with this permission"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Show Assistant microphone usage"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Unused app settings"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Remove permissions if app isn’t used"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Remove permissions and free up space"</string>
+ <string name="unused_apps_label_v2" msgid="7058776770056517980">"Pause app activity if unused"</string>
+ <string name="unused_apps_summary" msgid="8839466950318403115">"Remove permissions, delete temporary files and stop notifications"</string>
<string name="auto_revoke_summary" msgid="5867548789805911683">"To protect your data, permissions for this app will be removed if the app is unused for a few months."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"To protect your data, if the app is unused for a few months, the following permissions will be removed: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"To protect your data, permissions have been removed from apps that you haven’t used in a few months."</string>
@@ -264,8 +267,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"While driving, you gave <xliff:g id="APP">%1$s</xliff:g> access to <xliff:g id="PERMISSION_1">%2$s</xliff:g> &amp; <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"While driving, you granted <xliff:g id="COUNT">%1$d</xliff:g> permissions to <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{While driving, you gave <xliff:g id="APP_0">%1$s</xliff:g> &amp; # other app access}other{While driving, you gave <xliff:g id="APP_1">%1$s</xliff:g> &amp; # other apps access}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Go to Settings"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Some apps haven’t been used for a few months"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Removed permissions"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Permissions removed"</string>
@@ -468,10 +470,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your phone call logs?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to make and manage phone calls?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access sensor data about your vital signs?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"This app wants to access sensor data about your vital signs all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"This app wants to access sensor data about your vital signs all the time, even when you’re not using the app. To make this change, "<annotation id="link">"go to Settings."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access the sensor data about your vital signs?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"This app may want to access the sensor data about your vital signs all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Change access to sensor data about your vital signs for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"To let this app access body sensor data all the time, even when you\'re not using the app, "<annotation id="link">"go to settings."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Keep allowing &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access body sensor data while the app is in use?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to send you notifications?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to continue sending you notifications?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Controlled permissions"</string>
@@ -509,6 +511,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Remove camera permission"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Remove microphone permission"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Manage service"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Manage permissions"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Being used by phone call"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Recently used in phone call"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Being used by <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-en-rXC/strings.xml b/PermissionController/res/values-en-rXC/strings.xml
index 9e710212d..ba656701d 100644
--- a/PermissionController/res/values-en-rXC/strings.xml
+++ b/PermissionController/res/values-en-rXC/strings.xml
@@ -196,8 +196,11 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‎‏‎‎‏‏‎‏‏‎‎‎‎‎‎‏‎‏‎‎‎‎‎‎‎‏‎‎‏‏‎‎‎‎‎‎‏‎See all ‎‏‎‎‏‏‎<xliff:g id="APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎ permissions‎‏‎‎‏‎"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‎‏‎‎‏‏‎‎‎‎‎‏‎‏‎‏‎‎‎‏‏‎‎‏‎‏‎‏‎‎‎‎‎‏‏‎‏‏‏‎‎‎‎‎‏‏‎‏‎‏‏‏‎See all apps with this permission‎‏‎‎‏‎"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‎‎‏‎‏‎‏‎‏‎‎‎‏‎‏‏‏‏‎‏‎‏‏‏‎‏‎‎‏‏‎‎‏‏‎‎‏‏‏‏‎‎‏‎‎‏‏‏‎‎‎‎Show assistant microphone usage‎‏‎‎‏‎"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‎‏‎‎‏‎‎‎‎‎‏‎‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎‎‏‎‏‎‎‏‏‏‎‎‏‎‏‏‏‏‏‏‏‎‏‎Unused app settings‎‏‎‎‏‎"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‎‏‏‎‏‎‎‎‏‏‎‏‎‎‏‎‏‎‏‎‎‎‏‎‏‏‎‏‎‎‎‏‎‏‎‏‎‎‎‏‎‏‏‏‎‎‎‎‏‎‎‎‎Remove permissions if app isn’t used‎‏‎‎‏‎"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‎‎‎‏‎‎‏‏‎‏‎‎‎‎‏‎‏‏‎‏‏‎‏‎‏‏‎‏‎‎‏‎‎‏‏‎‏‎‏‎‎‎‏‏‎‎‏‏‎‎‏‎‎‎‎Remove permissions and free up space‎‏‎‎‏‎"</string>
+ <string name="unused_apps_label_v2" msgid="7058776770056517980">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‏‎‏‎‏‏‏‎‏‎‎‎‎‎‎‎‏‎‎‏‎‏‏‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‎‏‏‏‎‎‎Pause app activity if unused‎‏‎‎‏‎"</string>
+ <string name="unused_apps_summary" msgid="8839466950318403115">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‎‎‎‎‎‏‏‎‎‎‎‏‎‏‏‎‏‏‏‎‎‏‏‎‎‏‏‎‎‎‏‎‎‎‏‎‏‎‏‏‏‎‎‎‏‎‏‎‏‏‎Remove permissions, delete temporary files, and stop notifications‎‏‎‎‏‎"</string>
<string name="auto_revoke_summary" msgid="5867548789805911683">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‎‏‏‎‏‏‎‏‏‏‎‎‎‏‎‎‎‏‎‎‏‎‏‏‎‎‏‏‎‏‎‏‎‎‏‏‏‏‎‎‎‏‏‏‎‏‎‎‎‎‎‏‏‎To protect your data, permissions for this app will be removed if the app is unused for a few months.‎‏‎‎‏‎"</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‎‏‏‎‏‎‎‎‏‎‎‎‏‎‎‏‎‎‎‏‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‏‎‏‎‏‏‎‏‎‎‏‎‎‏‎‏‎‏‎To protect your data, if the app is unused for a few months, the following permissions will be removed: ‎‏‎‎‏‏‎<xliff:g id="PERMS">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‏‎‏‎‏‎‎‎‏‎‏‏‎‎‎‎‎‏‎‏‏‏‎‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‎‎‏‏‏‏‎‎‎‎To protect your data, permissions have been removed from apps that you haven’t used in a few months.‎‏‎‎‏‎"</string>
@@ -264,8 +267,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎‏‎‏‎‏‎‏‏‏‎‏‎‎‎‎‏‎‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‏‎‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‏‎While driving, you gave ‎‏‎‎‏‏‎<xliff:g id="APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎ access to ‎‏‎‎‏‏‎<xliff:g id="PERMISSION_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎ &amp; ‎‏‎‎‏‏‎<xliff:g id="PERMISSION_2">%3$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‏‎‎‎‎‏‏‎‎‏‎‎‎‎‏‎‏‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‏‏‏‏‏‏‎‎‎‎‎‏‎‎‏‏‏‏‏‎While driving, you granted ‎‏‎‎‏‏‎<xliff:g id="COUNT">%1$d</xliff:g>‎‏‎‎‏‏‏‎ permissions to ‎‏‎‎‏‏‎<xliff:g id="APP">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‏‎‎‏‏‎‎‎‏‎‏‎‏‎‎‎‏‎‏‏‎‏‎‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‏‎‎‎‏‏‏‎‎‏‏‏‏‎‎While driving, you gave ‎‏‎‎‏‏‎<xliff:g id="APP_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎ &amp; # other app access‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‏‎‎‏‏‎‎‎‏‎‏‎‏‎‎‎‏‎‏‏‎‏‎‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‏‎‎‎‏‏‏‎‎‏‏‏‏‎‎While driving, you gave ‎‏‎‎‏‏‎<xliff:g id="APP_1">%1$s</xliff:g>‎‏‎‎‏‏‏‎ &amp; # other apps access‎‏‎‎‏‎}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‏‏‎‏‎‎‏‏‎‏‎‏‎‏‎‎‎‎‎‏‏‏‎‏‏‎‏‏‏‎‏‎‏‎‏‏‏‏‎Go to Settings‎‏‎‎‏‎"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‎‏‎‎‎‎‎‏‎‎‎‎‎‏‎‎‎‎‎‎‏‎‏‎‎‏‎‎‏‏‎‎‎‎‏‎‎‏‎‎‎‏‏‏‏‎‏‏‏‎‎‎Some apps haven’t been used in a few months‎‏‎‎‏‎"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‎‎‎‏‏‎‏‏‎‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‎‏‎‏‎‏‎‏‎‏‎‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‎‏‏‎Removed permissions‎‏‎‎‏‎"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‎‏‏‎‏‎‎‎‎‏‏‏‎‏‎‎‎‎‏‏‎‎‏‎‎‏‏‎‎‎‏‏‎‏‏‏‏‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‎Permissions removed‎‏‎‎‏‎"</string>
@@ -468,10 +470,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‎‏‎‎‏‏‎‎‎‎‏‎‎‎‎‏‎‎‎‎‎‏‎‏‏‎‏‏‏‎‏‎‎‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access your phone call logs?‎‏‎‎‏‎"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‎‏‏‎‎‎‏‎‏‎‏‏‏‏‏‎‏‏‎‎‎‎‎‏‏‎‎‎‎‎‏‎‏‎‏‏‏‏‏‎‎‏‎‎‏‎‎‎‏‎‎‏‎‎‎‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to make and manage phone calls?‎‏‎‎‏‎"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‎‎‏‏‎‏‎‎‎‏‏‏‎‎‎‎‏‎‏‏‏‎‏‎‎‏‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‎‎‎‏‎‎‏‎‏‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access sensor data about your vital signs?‎‏‎‎‏‎"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‏‏‎‏‎‏‎‏‏‏‎‎‏‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‎‎‎‏‎‎‎‏‏‏‏‏‎‎‏‏‏‏‏‎‏‎‏‎This app wants to access sensor data about your vital signs all the time, even when you’re not using the app. ‎‏‎‎‏‏‎"<annotation id="link">"‎‏‎‎‏‏‏‎Allow in settings.‎‏‎‎‏‏‎"</annotation>"‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‏‎‎‎‎‎‏‎‏‏‎‎‎‏‎‎‏‎‏‎‏‏‎‎‎‎‎‏‎‏‎‏‎‏‏‏‎‏‏‏‎‎‎‎‎‏‎‏‎‎‎‏‏‎This app wants to access sensor data about your vital signs all the time, even when you’re not using the app. To make this change, ‎‏‎‎‏‏‎"<annotation id="link">"‎‏‎‎‏‏‏‎go to settings.‎‏‎‎‏‏‎"</annotation>"‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‏‏‎‎‏‏‎‎‏‎‎‎‏‎‏‏‎‎‎‎‏‏‎‏‏‏‎‎‎‎‏‏‏‎‏‎‏‎‏‏‎‎‏‏‎‎‏‏‏‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access the sensor data about your vital signs?‎‏‎‎‏‎"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‎‏‎‏‎‏‎‏‏‎‎‏‏‎‎‎‏‏‏‎‏‏‎‎‎‎‏‏‎‏‏‎‎‎‎This app may want to access the sensor data about your vital signs all the time, even when you’re not using the app. ‎‏‎‎‏‏‎"<annotation id="link">"‎‏‎‎‏‏‏‎Allow in settings.‎‏‎‎‏‏‎"</annotation>"‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‎‏‏‏‎‎‎‎‎‏‎‎‏‏‎‏‏‎‎‏‎‏‏‎‏‏‎‏‏‏‎‏‏‏‏‏‎‏‎‎‏‎‎‏‏‎‏‎‏‏‏‎‏‎‏‏‎Change access to sensor data about your vital signs for &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‎‏‎‎‎‎‎‎‏‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‎‎‏‏‎‏‏‏‎‏‏‎‏‏‏‎‏‏‎‏‎‎‏‏‏‎‏‏‏‎To let this app access body sensor data all the time, even when you’rere not using the app, ‎‏‎‎‏‏‎"<annotation id="link">"‎‏‎‎‏‏‏‎go to settings.‎‏‎‎‏‏‎"</annotation>"‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‎‏‎‏‎‎‏‏‏‎‏‏‏‎‏‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎Keep allowing &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access body sensor data while app is in use?‎‏‎‎‏‎"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‎‎‏‎‏‏‏‎‎‏‎‎‎‎‏‎‎‏‎‎‏‎‎‏‎‏‎‏‏‎‏‎‏‏‎‎‏‎‏‏‎‏‏‎‎‏‎‎‎‎‏‎‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to send you notifications?‎‏‎‎‏‎"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‎‎‏‏‏‎‎‎‏‎‏‎‏‏‎‎‎‏‎‏‏‏‎‏‏‎‏‏‏‎‎‎‏‏‎‎‎‏‎‏‎‎‏‎‏‎‏‎‎‏‏‎‏‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to continue sending you notifications?‎‏‎‎‏‎"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‎‎‏‎‏‏‏‎‏‏‏‎‎‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‏‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‎‏‎‎‎Controlled permissions‎‏‎‎‏‎"</string>
@@ -509,6 +511,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‎‏‎‎‏‎‎‏‎‏‎‎‏‏‏‎‏‎‎‎‎‎‎‏‎‎‎‏‎‎‏‎‎‎‏‎‏‎‎Remove camera permission‎‏‎‎‏‎"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‏‏‎‎‎‎‎‏‏‏‎‎‏‎‎‎‎‏‏‏‎‎‎‏‎‏‏‎‎‏‏‏‎‏‏‏‎Remove microphone permission‎‏‎‎‏‎"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‏‏‎‏‎‏‏‎‏‎‎‎‏‎‎‏‏‏‎‏‎‏‎‏‎‎‏‎‏‎‏‎‎‎‎‎‎‏‏‎‏‏‎‏‏‏‎‎‏‏‎‏‎Manage service‎‏‎‎‏‎"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‏‏‎‏‏‏‎‎‏‎‏‏‏‎‏‏‎‎‎‎‎‏‎‏‎‎‎‎‎‏‏‎‎‎‎‎‏‎‏‏‎‎‎‎‏‏‏‏‏‎‏‎‏‎‎Manage permissions‎‏‎‎‏‎"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‏‏‎‎‏‎‎‎‏‏‎‏‎‏‏‏‎‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‏‏‏‏‏‎Being used by phone call‎‏‎‎‏‎"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‏‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‎‎‏‏‎‎‎‏‏‏‏‎‎‏‏‎‎‏‎‎‏‏‏‏‎‎‏‏‎‏‏‏‏‎‏‏‏‎Recently used in phone call‎‏‎‎‏‎"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‎‎‏‎‏‏‏‏‎‏‎‏‏‎‎‏‏‏‎‎‏‎‏‏‏‏‏‏‎‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎‏‎‏‎‏‎‏‏‏‎Being used by ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
diff --git a/PermissionController/res/values-es-rUS/strings.xml b/PermissionController/res/values-es-rUS/strings.xml
index fc1566bfb..21a52635a 100644
--- a/PermissionController/res/values-es-rUS/strings.xml
+++ b/PermissionController/res/values-es-rUS/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Ver todos los permisos de <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Ver todas las apps que tienen este permiso"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Mostrar el uso del micrófono del Asistente"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Configuración de apps sin usar"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Quitar los permisos si la app no se usa"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Quitar permisos y liberar espacio"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Para proteger tus datos, se quitarán los permisos de esta app si no la usas durante varios meses."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Para proteger tus datos, si no usas la app durante varios meses, se quitarán los siguientes permisos: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Para proteger tus datos, se quitaron los permisos de las apps que están en desuso hace varios meses."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Mientras conducías, le otorgaste acceso a <xliff:g id="APP">%1$s</xliff:g> a <xliff:g id="PERMISSION_1">%2$s</xliff:g> y <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Mientras conducías, le otorgaste <xliff:g id="COUNT">%1$d</xliff:g> permisos a <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Mientras conducías, les otorgaste acceso a <xliff:g id="APP_0">%1$s</xliff:g> y otra app}other{Mientras conducías, les otorgaste acceso a <xliff:g id="APP_1">%1$s</xliff:g> y otras # apps}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Ir a Configuración"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Hace varios meses que no usas algunas apps"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Apps a las que se les quitaron permisos"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Permisos que se quitaron"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda al registro de las llamadas telefónicas?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; haga y administre las llamadas telefónicas?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a los datos de sensores de tus signos vitales?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Esta app quiere acceder a los datos de los sensores de tus signos vitales todo el tiempo, incluso cuando no la usas. "<annotation id="link">"Puedes permitirlo en configuración."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Esta app quiere acceder a los datos de sensores de tus signos vitales todo el tiempo, incluso cuando no la usas. Para realizar este cambio, "<annotation id="link">"ve a configuración."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"¿Quieres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a los datos de los sensores de tus signos vitales?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Esta app podría querer acceder a los datos de tus signos vitales todo el tiempo, incluso cuando no la uses. "<annotation id="link">"Puedes permitirlo en la configuración."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"¿Quieres cambiar el acceso de &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; a los datos de los sensores de tus signos vitales?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Para permitir que esta app acceda a datos del sensor corporal todo el tiempo, incluso cuando no la uses, "<annotation id="link">"ve a la configuración."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"¿Quieres seguir permitiendo que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a datos del sensor corporal mientras está en uso?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"¿Quieres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; te envíe notificaciones?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"¿Quieres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; siga enviándote notificaciones?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Permisos controlados"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Quitar el permiso de la cámara"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Quitar el permiso del micrófono"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Administrar servicio"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Administrar permisos"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"En uso en una llamada telefónica"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Uso reciente en una llamada telefónica"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"En uso en <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-es/strings.xml b/PermissionController/res/values-es/strings.xml
index 82e46c5de..8c43404b5 100644
--- a/PermissionController/res/values-es/strings.xml
+++ b/PermissionController/res/values-es/strings.xml
@@ -160,7 +160,7 @@
<string name="permission_usage_bar_chart_title_last_minute" msgid="820450867183487607">"Uso de permisos en el último minuto"</string>
<string name="permission_usage_preference_summary_not_used_24h" msgid="3087783232178611025">"No se ha usado en las últimas 24 horas"</string>
<string name="permission_usage_preference_summary_not_used_7d" msgid="4592301300810120096">"No se ha usado en los últimos 7 días"</string>
- <string name="permission_usage_preference_label" msgid="8343167938128676378">"{count,plural, =1{Usado por 1 aplicación}other{Usado por # aplicaciones}}"</string>
+ <string name="permission_usage_preference_label" msgid="8343167938128676378">"{count,plural, =1{Se ha dado permiso a 1 aplicación}other{Se ha dado permiso a # aplicaciones}}"</string>
<string name="permission_usage_view_details" msgid="6675335735468752787">"Ver todo en el panel de control"</string>
<string name="app_permission_usage_filter_label" msgid="7182861154638631550">"Filtrados por: <xliff:g id="PERM">%1$s</xliff:g>"</string>
<string name="app_permission_usage_remove_filter" msgid="2926157607436428207">"Quitar filtro"</string>
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Ver todos los permisos de <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Ver todas las aplicaciones con este permiso"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Mostrar el uso del micrófono del Asistente"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Configuración de aplicaciones sin usar"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Quitar permisos si la aplicación no se usa"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Quitar permisos y liberar espacio"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Para proteger tus datos, se quitarán los permisos de esta aplicación si no la usas durante unos meses."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Para proteger tus datos, si la aplicación no se ha utilizado durante unos meses, se quitarán los siguientes permisos: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Para proteger tus datos, se han quitado los permisos de las aplicaciones que llevas unos meses sin usar."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Durante la conducción, has dado a <xliff:g id="APP">%1$s</xliff:g> permiso de <xliff:g id="PERMISSION_1">%2$s</xliff:g> y <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Durante la conducción, has dado <xliff:g id="COUNT">%1$d</xliff:g> permisos a <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Durante la conducción, has dado acceso a <xliff:g id="APP_0">%1$s</xliff:g> y otra aplicación}other{Durante la conducción, has dado acceso a <xliff:g id="APP_1">%1$s</xliff:g> y otras # aplicaciones}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Ir a Ajustes"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Hay varias aplicaciones que llevan meses sin usarse"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Permisos quitados"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Permisos quitados"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a los registros de llamadas del teléfono?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; haga y gestione llamadas?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a los datos del sensor sobre tus constantes vitales?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Esta aplicación quiere acceder a los datos de sensores de tus constantes vitales siempre, incluso aunque no la uses. "<annotation id="link">"Puedes permitirlo en Ajustes."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Esta aplicación quiere acceder a los datos de sensores de tus constantes vitales todo el tiempo, incluso cuando no la uses. Para hacer este cambio, "<annotation id="link">"ve a los ajustes"</annotation>"."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"¿Quieres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a los datos de sensores de tus constantes vitales?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Esta aplicación quiere acceder a los datos de sensores de tus constantes vitales siempre, incluso aunque no la uses. "<annotation id="link">"Puedes permitirlo en Ajustes."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"¿Quieres cambiar el acceso de &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; a los datos de sensores sobre tus constantes vitales?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Para permitir que esta aplicación acceda siempre a los datos del sensor corporal, incluso cuando no la uses, "<annotation id="link">"ve a los ajustes."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a los datos del sensor corporal mientras se usa?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"¿Quieres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; te envíe notificaciones?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"¿Quieres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; siga enviándote notificaciones?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Permisos controlados"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Retirar el permiso de la cámara"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Retirar el permiso del micrófono"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Gestionar servicio"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Gestionar permisos"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Se está usando en llamada telefónica"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Uso reciente en llamada telefónica"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Se está usando en <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-et/strings.xml b/PermissionController/res/values-et/strings.xml
index 5d636f05c..587888123 100644
--- a/PermissionController/res/values-et/strings.xml
+++ b/PermissionController/res/values-et/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Kuva rakenduse <xliff:g id="APP">%1$s</xliff:g> kõik load"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Kuva kõik selle loaga rakendused"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Kuva assistendi mikrofoni kasutamine"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Kasutamata rakenduste seaded"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Eemalda load, kui rakendust ei kasutata"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Eemalda load ja vabasta ruumi"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Teie andmete kaitsmiseks eemaldatakse selle rakenduse load, kui seda mõne kuu jooksul ei kasutata."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Teie andmete kaitsmiseks eemaldatakse selle rakenduse järgmised load, kui rakendust mõne kuu jooksul ei kasutata: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Teie andmete kaitsmiseks eemaldati load rakendustelt, mida te ei ole mõne kuu jooksul kasutanud."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Andsite sõidu ajal rakendusele <xliff:g id="APP">%1$s</xliff:g> juurdepääsu lubadele <xliff:g id="PERMISSION_1">%2$s</xliff:g> ja <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Andsite sõidu ajal rakendusele <xliff:g id="APP">%2$s</xliff:g> <xliff:g id="COUNT">%1$d</xliff:g> luba"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Andsite sõidu ajal rakendusele <xliff:g id="APP_0">%1$s</xliff:g> ja veel # rakendusele juurdepääsu}other{Andsite sõidu ajal rakendusele <xliff:g id="APP_1">%1$s</xliff:g> ja veel # rakendusele juurdepääsu}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Ava seaded"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Mõningaid rakendusi ei ole mõne kuu jooksul kasutatud"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Eemaldatud load"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Eemaldatud load"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Kas lubada rakendusel &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pääseda juurde teie telefoni kõnelogidele?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Kas lubada rakendusel &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; teha ja hallata telefonikõnesid?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Kas lubada rakendusele &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; juurdepääs anduri andmetele teie eluliste näitajate kohta?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"See rakendus soovib pidevat juurdepääsu anduri andmetele teie eluliste näitajate kohta, isegi kui te rakendust ei kasuta. "<annotation id="link">"Lubage see seadetes."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"See rakendus soovib pidevat juurdepääsu teie elulistele näitajatele (ka siis, kui te rakendust ei kasuta). Selle muudatuse tegemiseks "<annotation id="link">"avage seaded."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Kas lubada rakendusele &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; juurdepääs anduri andmetele teie eluliste näitajate kohta?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"See rakendus võib soovida pidevat juurdepääsu anduri andmetele teie eluliste näitajate kohta, isegi kui te rakendust ei kasuta. "<annotation id="link">"Lubage see seadetes."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Kas muuta rakenduse &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; jaoks juurdepääsu anduri andmetele teie eluliste näitajate kohta?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Selleks et anda rakendusele pidev juurdepääs kehaanduri andmetele (ka siis, kui rakendust ei kasutata), "<annotation id="link">"avage seaded."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Kas lubada jätkuvalt rakendusel &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pääseda juurde kehaanduri andmetele, kui rakendust kasutatakse?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Kas lubada rakendusel &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; teile märguandeid saata?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Kas lubada rakendusel &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; teile jätkuvalt märguandeid saata?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Hallatud load"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Eemalda kaamera luba"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Eemalda mikrofoni luba"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Teenuse haldamine"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Lubade haldamine"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Kasutatakse telefonikõne jaoks"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Kasutati hiljuti telefonikõne jaoks"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Kasutab rakendus <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-eu/strings.xml b/PermissionController/res/values-eu/strings.xml
index f3ebd8c5c..7bfd0eb17 100644
--- a/PermissionController/res/values-eu/strings.xml
+++ b/PermissionController/res/values-eu/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Ikusi <xliff:g id="APP">%1$s</xliff:g> aplikazioaren baimen guztiak"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Ikusi baimen hau duten aplikazio guztiak"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Erakutsi laguntzaileak mikrofonoa erabiltzeko duen baimena"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Erabili gabeko aplikazio-ezarpenak"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Kendu baimenak aplikazioa ez bada erabiltzen"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Kendu baimenak eta egin tokia"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Zure datuak babeste aldera, aplikazio honen baimenak kendu egingo dira aplikazioa ez baduzu erabiltzen zenbait hilabetez."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Zure datuak babeste aldera, kendu egingo dira honako baimen hauek zenbait hilabetez aplikazioa erabiltzen ez baduzu: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Zure datuak babeste aldera, kendu egin dira zenbait hilabetez erabili ez dituzun aplikazioen baimenak."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Gidatu bitartean, <xliff:g id="PERMISSION_1">%2$s</xliff:g> eta <xliff:g id="PERMISSION_2">%3$s</xliff:g> atzitzeko baimena eman diozu <xliff:g id="APP">%1$s</xliff:g> aplikazioari"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Gidatu bitartean, <xliff:g id="COUNT">%1$d</xliff:g> baimen eman dizkiozu <xliff:g id="APP">%2$s</xliff:g> aplikazioari"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Gidatu bitartean, baimenak eman dizkiezu <xliff:g id="APP_0">%1$s</xliff:g> eta beste # aplikaziori}other{Gidatu bitartean, baimenak eman dizkiezu <xliff:g id="APP_1">%1$s</xliff:g> eta beste # aplikaziori}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Joan ezarpenetara"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Aplikazio batzuk ez dira erabili zenbait hilabetez"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Baimenak kendu zaizkien aplikazioak"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Baimenak kendu zaizkien aplikazioak"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Telefonoko deien erregistroa atzitzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Telefono-deiak egiteko eta kudeatzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Bizi-konstanteei buruzko sentsorearen datuak atzitzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Aplikazioak bizi-konstanteei buruzko sentsoreen datuak beti atzitzeko baimena behar du, baita aplikazioa erabiltzen ari ez zarenean ere. "<annotation id="link">"Eman baimen hori Ezarpenak atalean."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Aplikazioak bizi-konstanteei buruzko sentsoreen datuak atzitu nahi ditu, baita aplikazioa erabiltzen ari ez zarenean ere. Aldaketa hori egiteko, "<annotation id="link">"joan ezarpenetara."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Bizi-konstanteei buruzko sentsoreen datuak atzitzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Baliteke aplikazioak bizi-konstanteei buruzko sentsoreen datuak atzitzeko baimena behar izatea, baita aplikazioa erabiltzen ari ez zarenean ere. "<annotation id="link">"Eman baimena ezarpenetan."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioak bizi-konstanteei buruzko sentsoreen datuak atzitzeko duen baimena aldatu nahi duzu?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Aplikazioari gorputz-sentsoreen datuak beti (baita aplikazioa erabiltzen ari ez zarenean ere) atzitzeko baimena emateko, "<annotation id="link">"joan ezarpenetara."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erabili bitartean gorputz-sentsoreen datuak atzitzeko baimena eman nahi diozu aplikazio horri?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Zuri jakinarazpenak bidaltzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Zuri jakinarazpenak bidaltzen jarraitzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Kontrolatutako baimenak"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Kendu kamera atzitzeko baimena"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Kendu mikrofonoa atzitzeko baimena"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Kudeatu zerbitzua"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Kudeatu baimenak"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Telefono-deiak darabil"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Telefono-deian erabili da duela gutxi"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioak darabil"</string>
diff --git a/PermissionController/res/values-fa/strings.xml b/PermissionController/res/values-fa/strings.xml
index 32c5c86a2..2013f8196 100644
--- a/PermissionController/res/values-fa/strings.xml
+++ b/PermissionController/res/values-fa/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"مشاهده همه اجازه‌های <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"دیدن همه برنامه‌هایی که این مجوز را دارند"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"نمایش میزان استفاده «دستیار» از میکروفون"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"تنظیمات برنامه‌های استفاده‌نشده"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"اگر از برنامه استفاده نمی‌شود، اجازه‌ها برداشته شوند"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"برداشتن اجازه‌ها و آزاد کردن فضا"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"برای محافظت از داده‌هایتان، اگر طی چند ماه گذشته از این برنامه استفاده نشده باشد، اجازه‌های آن برداشته خواهد شد."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"برای محافظت از داده‌هایتان، اگر طی چند ماه گذشته از این برنامه استفاده نشده باشد، اجازه‌های زیر برداشته خواهد شد: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"برای محافظت از داده‌هایتان، اجازه‌ها از برنامه‌هایی که طی چند ماه گذشته استفاده نشده‌اند برداشته شده است."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"درحین رانندگی، به <xliff:g id="APP">%1$s</xliff:g> اجازه دادید به <xliff:g id="PERMISSION_1">%2$s</xliff:g> و <xliff:g id="PERMISSION_2">%3$s</xliff:g> دسترسی داشته باشد"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"درحین رانندگی، <xliff:g id="COUNT">%1$d</xliff:g> اجازه به <xliff:g id="APP">%2$s</xliff:g> اعطا کردید"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{درحین رانندگی، به <xliff:g id="APP_0">%1$s</xliff:g> و # برنامه دیگر اجازه دسترسی دادید}one{درحین رانندگی، به <xliff:g id="APP_1">%1$s</xliff:g> و # برنامه دیگر اجازه دسترسی دادید}other{درحین رانندگی، به <xliff:g id="APP_1">%1$s</xliff:g> و # برنامه دیگر اجازه دسترسی دادید}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"رفتن به «تنظیمات»"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"برخی از برنامه‌ها به‌مدت چند ماه استفاده نشده‌اند"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"اجازه‌های برداشته‌شده"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"اجازه‌ها برداشته شد"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود به گزارش تماس‌های تلفنی شما دسترسی داشته باشد؟"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; اجازه داده شود تماس‌های تلفنی برقرار کند و آن‌ها را مدیریت کند؟"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; اجازه داده شود به داده‌های حسگر مربوط به علائم حیاتی شما دسترسی پیدا کند؟"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"این برنامه می‌خواهد همواره به داده‌های علائم حیاتی‌تان از حسگر دسترسی داشته باشد، حتی وقتی از برنامه استفاده نمی‌کنید. "<annotation id="link">"اجازه دادن در تنظیمات."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"این برنامه می‌خواهد به داده‌های حسگر از علائم حیاتی شما همیشه دسترسی داشته باشد، حتی زمانی که از برنامه استفاده نمی‌کنید. برای انجام این تغییر، "<annotation id="link">"به تنظیمات بروید."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه می‌دهید به داده‌های علائم حیاتی‌تان از حسگر دسترسی داشته باشد؟"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"این برنامه ممکن است بخواهد همواره به داده‌های علائم حیاتی‌تان از حسگر دسترسی داشته باشد، حتی وقتی از برنامه استفاده نمی‌کنید. "<annotation id="link">"اجازه دادن در تنظیمات."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"‏دسترسی به داده‌های علائم حیاتی‌تان از حسگر برای &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; تغییر کند؟"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"برای اینکه این برنامه بتواند همواره به داده‌های حسگر بدن دسترسی داشته باشد، حتی زمانی که از برنامه استفاده نمی‌کنید، "<annotation id="link">"به تنظیمات بروید."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; همچنان اجازه داده شود درحین استفاده، به داده‌های حسگر بدن دسترسی داشته باشد؟"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود اعلان ارسال کند؟"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود همچنان اعلان ارسال کند؟"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"مجوزهای کنترل‌شده"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"برداشتن اجازه دوربین"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"برداشتن اجازه میکروفون"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"مدیریت سرویس"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"مدیریت اجازه‌ها"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"تماس تلفنی درحال استفاده از آن است"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"اخیراً تماس تلفنی از آن استفاده کرده است"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> درحال استفاده از آن است"</string>
diff --git a/PermissionController/res/values-fi/strings.xml b/PermissionController/res/values-fi/strings.xml
index 096656598..16f3c84cd 100644
--- a/PermissionController/res/values-fi/strings.xml
+++ b/PermissionController/res/values-fi/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Näytä kaikki luvat, jotka <xliff:g id="APP">%1$s</xliff:g> on saanut"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Näytä kaikki sovellukset, joilla on tämä lupa"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Näytä Assistantin mikrofonin käyttö"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Käyttämättömät sovellusasetukset"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Poista luvat, jos sovellusta ei käytetä"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Poista lupia ja vapauta tilaa"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Datasi suojaamiseksi tämän sovelluksen luvat poistetaan, jos sovellusta ei käytetä muutamaan kuukauteen."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Jos sovellusta ei käytetä muutamaan kuukauteen, seuraavat luvat poistetaan datasi suojaamiseksi: <xliff:g id="PERMS">%1$s</xliff:g>."</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Datasi suojaamiseksi luvat on poistettu sovelluksilta, joita et ole käyttänyt muutamaan kuukauteen."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"<xliff:g id="APP">%1$s</xliff:g> sai ajon aikana nämä luvat: <xliff:g id="PERMISSION_1">%2$s</xliff:g> ja <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"<xliff:g id="COUNT">%1$d</xliff:g> sai ajon aikana <xliff:g id="APP">%2$s</xliff:g> lupaa"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{<xliff:g id="APP_0">%1$s</xliff:g> ja # muu sovellus saivat pääsyn ajon aikana}other{<xliff:g id="APP_1">%1$s</xliff:g> ja # muuta sovellusta saivat pääsyn ajon aikana}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Siirry asetuksiin"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Joitain sovelluksia ei ole käytetty muutamaan kuukauteen"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Poistetut luvat"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Luvat poistettu"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; puhelulokien käyttöoikeuden?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; soittaa ja hallinnoida puheluita?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; käyttää anturitietoja elintoiminnoistasi?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Sovellus haluaa pääsyn elintoimintojen anturidataan aina, myös silloin kun et käytä sitä. "<annotation id="link">"Myönnä lupa asetuksista"</annotation>"."</string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Sovellus haluaa pääsyn elintoimintojasi koskevaan anturidataan aina, myös silloin, kun et käytä sovellusta. Voit myöntää luvan "<annotation id="link">"asetuksista"</annotation>"."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; käyttää anturidataa elintoiminnoistasi?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Sovellus voi haluta pääsyn elintoimintojesi anturidataan aina, myös silloin kun et käytä sitä. "<annotation id="link">"Myönnä lupa asetuksista"</annotation>"."</string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Muutetaanko pääsyoikeutta, jonka &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; on saanut elintoimintojesi anturidataan?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Jos haluat myöntää sovellukselle pääsyn kehoanturidataan aina, myös silloin, kun et käytä sovellusta, siirry "<annotation id="link">"asetuksiin"</annotation>"."</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Haluatko edelleen sallia pääsyn kehoanturidataan, kun &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; on käytössä?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; lähettää sinulle ilmoituksia?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; jatkaa ilmoitusten lähettämistä?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Automaattisesti myönnetyt käyttöoikeudet"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Poista kameralupa"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Poista mikrofonilupa"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Ylläpidä palvelua"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Lupien valitseminen"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Puhelu käyttää tätä"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Käytetty äskettäin puhelussa"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> käyttää tätä"</string>
diff --git a/PermissionController/res/values-fr-rCA/strings.xml b/PermissionController/res/values-fr-rCA/strings.xml
index ce28070e3..5a91c07d4 100644
--- a/PermissionController/res/values-fr-rCA/strings.xml
+++ b/PermissionController/res/values-fr-rCA/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Afficher toutes les autorisations pour <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Afficher toutes les applications qui possèdent cette autorisation"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Afficher l\'usage du microphone de l\'assistant"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Paramètres des applications inutilisées"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Retirer les autorisations si l\'application est inutilisée"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Retirer autorisations et libérer espace"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Afin de protéger vos données, les autorisations pour cette application seront supprimées si elle n\'est pas utilisée pendant quelques mois."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Afin de protéger vos données, si l\'application n\'est pas utilisée pendant quelques mois, les autorisations suivantes seront supprimées : <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Afin de protéger vos données, les autorisations ont été supprimées pour les applications que vous n\'avez pas utilisées depuis quelques mois."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Pendant la conduite, vous avez donné à <xliff:g id="APP">%1$s</xliff:g> l\'accès à <xliff:g id="PERMISSION_1">%2$s</xliff:g> et à <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Pendant la conduite, vous avez accordé <xliff:g id="COUNT">%1$d</xliff:g> autorisations à <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Pendant la conduite, vous avez donné l\'accès à <xliff:g id="APP_0">%1$s</xliff:g> et à # autre application}one{Pendant la conduite, vous avez donné l\'accès à <xliff:g id="APP_1">%1$s</xliff:g> et à # autre application}other{Pendant la conduite, vous avez donné l\'accès à <xliff:g id="APP_1">%1$s</xliff:g> et à # autres applications}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Accéder aux paramètres"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Certaines applications n\'ont pas été utilisées depuis quelques mois"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Autorisations supprimées"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Autorisations supprimées"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder à vos journaux d\'appels?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à faire et à gérer des appels téléphoniques?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Autoriser « <xliff:g id="APP_NAME">%1$s</xliff:g> » à accéder aux données des capteurs pour vos signes vitaux?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Cette appli veut accéder aux données des capteurs sur vos signes vitaux en tout temps, même lorsque vous ne l\'utilisez pas. "<annotation id="link">"Autorisez dans Paramètres."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Cette application souhaite pouvoir accéder en tout temps aux données de capteurs relatives à vos signes vitaux, même lorsque vous ne l\'utilisez pas. Pour effectuer ce changement, "<annotation id="link">"accédez aux paramètres"</annotation>"."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Autoriser « <xliff:g id="APP_NAME">%1$s</xliff:g> » à accéder aux données des capteurs relatives à vos signes vitaux?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Cette appli peut toujours vouloir accéder aux données des capteurs pour vos signes vitaux, même lorsqu\'elle est inutilisée. "<annotation id="link">"Autorisez dans Paramètres."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Modifiez l\'accès aux données des capteurs relatives à vos signes vitaux pour « <xliff:g id="APP_NAME">%1$s</xliff:g> »?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Pour permettre à cette application d\'accéder aux données des capteurs corporels en tout temps, même lorsque vous n\'utilisez pas l\'application, "<annotation id="link">"accédez aux paramètres"</annotation>"."</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Voulez-vous continuer à autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder aux données des capteurs corporels pendant l\'utilisation de l\'appli?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Autorisez &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à vous envoyer des notifications?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à continuer à vous envoyer des notifications?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Autorisations contrôlées"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Retirer l\'autorisation de l\'appareil photo"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Retirer l\'autorisation du microphone"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Gérer le service"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Gérer les autorisations"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"En cours d\'utilisation par un appel téléphonique"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Récemment utilisé par un appel téléphonique"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"En cours d\'utilisation par <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-fr/strings.xml b/PermissionController/res/values-fr/strings.xml
index 5f35eb60f..3ffb06ae9 100644
--- a/PermissionController/res/values-fr/strings.xml
+++ b/PermissionController/res/values-fr/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Afficher toutes les autorisations pour <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Afficher toutes les applications disposant de cette autorisation"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Afficher l\'utilisation du micro par l\'Assistant"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Paramètres d\'appli inutilisés"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Supprimer les autorisations si l\'application n\'est pas utilisée"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Supprimer autorisations et libérer espace"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Si cette application n\'est pas utilisée pendant plusieurs mois, ses autorisations seront supprimées afin de protéger vos données."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Pour protéger vos données, si l\'application n\'est pas utilisée pendant plusieurs mois, les autorisations suivantes seront supprimées : <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Afin de protéger vos données, les autorisations ont été supprimées pour les applications que vous n\'avez pas utilisées depuis plusieurs mois."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"En conduisant, vous avez autorisé <xliff:g id="APP">%1$s</xliff:g> à accéder à : <xliff:g id="PERMISSION_1">%2$s</xliff:g> et <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"En conduisant, vous avez accordé <xliff:g id="COUNT">%1$d</xliff:g> autorisations à <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{En conduisant, vous avez accordé l\'accès à <xliff:g id="APP_0">%1$s</xliff:g> et # autre appli}one{En conduisant, vous avez accordé l\'accès à <xliff:g id="APP_1">%1$s</xliff:g> et # autre appli}other{En conduisant, vous avez accordé l\'accès à <xliff:g id="APP_1">%1$s</xliff:g> et # autres applis}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Paramètres"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Certaines applications n\'ont pas été utilisées depuis plusieurs mois"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Autorisations supprimées"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Autorisations supprimées"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder aux journaux d\'appels de votre téléphone ?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à passer et gérer des appels téléphoniques ?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Permettre à &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; d\'accéder aux données des capteurs relatives à vos signes vitaux ?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Cette appli souhaite accéder aux données des capteurs liées aux signes vitaux, même quand vous ne l\'utilisez pas. "<annotation id="link">"Autoriser dans les paramètres"</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Cette application veut accéder en permanence aux données des capteurs liées aux signes vitaux, même quand vous ne l\'utilisez pas. Pour autoriser ce changement, "<annotation id="link">"accédez aux paramètres."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder aux données des capteurs liées à vos signes vitaux ?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Cette appli peut souhaiter accéder aux données des capteurs liées aux signes vitaux, même quand vous ne l\'utilisez pas. "<annotation id="link">"Autoriser dans les paramètres"</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Modifier l\'accès aux données des capteurs liées aux signes vitaux pour &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Pour autoriser cette appli à accéder aux données des capteurs corporels en permanence, même quand vous ne l\'utilisez pas, "<annotation id="link">"accédez aux paramètres"</annotation>"."</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Continuer à autoriser <xliff:g id="APP_NAME">%1$s</xliff:g> à accéder aux données des capteurs corporels seulement en cours d\'utilisation ?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à vous envoyer des notifications ?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à continuer de vous envoyer des notifications ?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Autorisations contrôlées"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Supprimer l\'autorisation de l\'appareil photo"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Supprimer l\'autorisation du micro"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Gérer le service"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Gérer les autorisations"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Utilisé actuellement par un appel téléphonique"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Récemment utilisé lors d\'un appel téléphonique"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Utilisé actuellement par <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-gl/strings.xml b/PermissionController/res/values-gl/strings.xml
index 470e69058..201ea7d58 100644
--- a/PermissionController/res/values-gl/strings.xml
+++ b/PermissionController/res/values-gl/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Ver todos os permisos de <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Ver todas as aplicacións que teñen este permiso"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Mostrar uso do micrófono do Asistente"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Configuración das aplicacións sen uso"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Quitar permisos se non se usa a aplicación"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Quitar permisos e liberar espazo"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Para protexer os teus datos, quitaranse os permisos desta aplicación se pasas varios meses sen utilizala."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Para protexer os teus datos, se a aplicación leva varios meses sen usarse, quitaranse os seguintes permisos: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Para protexer os teus datos, quitáronse os permisos das aplicacións que levas varios meses sen usar."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Mentres conducías, décheslle á aplicación <xliff:g id="APP">%1$s</xliff:g> acceso ao seguinte: <xliff:g id="PERMISSION_1">%2$s</xliff:g> e <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Mentres conducías, décheslle <xliff:g id="COUNT">%1$d</xliff:g> permisos á aplicación <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Mentres conducías, décheslles acceso a <xliff:g id="APP_0">%1$s</xliff:g> e a # aplicación máis}other{Mentres conducías, décheslles acceso a <xliff:g id="APP_1">%1$s</xliff:g> e a # aplicacións máis}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Ir a Configuración"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Algunhas aplicacións levan varios meses sen usarse"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Permisos quitados"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Permisos quitados"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Queres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda aos rexistros de chamadas do teléfono?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Queres permitir que a aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; realice e xestione chamadas telefónicas?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Queres permitir que a aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda aos datos dos sensores sobre as túas constantes vitais?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Esta aplicación require acceso a datos dos sensores sobre as constantes vitais todo o tempo, mesmo cando non a usas. "<annotation id="link">"Podes permitilo na configuración"</annotation>"."</string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Esta aplicación require acceso aos datos dos sensores sobre as túas constantes vitais en todo momento, mesmo cando non a usas. Para facer este cambio, "<annotation id="link">"vai á configuración."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda aos datos dos sensores sobre as túas constantes vitais?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Quizais esta aplicación requira acceso a datos dos sensores sobre as constantes vitais, mesmo cando non a usas. "<annotation id="link">"Podes permitilo na configuración"</annotation>"."</string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Queres cambiar o acceso aos datos dos sensores sobre as constantes vitais para &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Para permitir que esta aplicación acceda aos datos dos sensores corporais en todo momento, aínda que non a esteas utilizando, "<annotation id="link">"vai á configuración"</annotation>"."</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Permites que a aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; siga accedendo aos datos dos sensores corporais mentres estea en uso?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Queres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; che envíe notificacións?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Queres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; siga enviándoche notificacións?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Permisos controlados"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Quitar permiso da cámara"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Quitar permiso do micrófono"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Xestionar servizo"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Administrar permisos"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"En uso nunha chamada telefónica"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"En uso recentemente nunha chamada telefónica"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"En uso por parte de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-gu/strings.xml b/PermissionController/res/values-gu/strings.xml
index fdd63f443..e00e41ab0 100644
--- a/PermissionController/res/values-gu/strings.xml
+++ b/PermissionController/res/values-gu/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"<xliff:g id="APP">%1$s</xliff:g>ની બધી પરવાનગીઓ જુઓ"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"આ પરવાનગી સાથે બધી ઍપ જુઓ"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"આસિસ્ટંટ દ્વારા વપરાયેલો માઇક્રોફોનની પરવાનગીનો ડેટા બતાવો"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"ન વપરાયેલી ઍપના સેટિંગ"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"ઍપ ઉપયોગમાં ન હોવા પર પરવાનગીઓ કાઢી નાખો"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"પરવાનગીઓ કાઢી નાખો અને જગ્યા ખાલી કરો"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"તમારા ડેટાની સુરક્ષા કરવા માટે, જો ઍપનો કેટલાક મહિનાથી ઉપયોગ કરવામાં આવ્યો ન હોય, તો આ ઍપની પરવાનગીઓ કાઢી નાખવામાં આવશે."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"તમારા ડેટાની સુરક્ષા કરવા માટે, જો ઍપનો કેટલાક મહિનાથી ઉપયોગ કરવામાં આવ્યો ન હોય, તો નીચેની પરવાનગીઓ કાઢી નાખવામાં આવશે: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"તમારા ડેટાની સુરક્ષા માટે, તમારા દ્વારા કેટલાક મહિનાથી ઉપયોગમાં ન લેવાયેલી ઍપની પરવાનગીઓ કાઢી નાખવામાં આવી છે."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"ડ્રાઇવ કરતી વખતે, તમે <xliff:g id="APP">%1$s</xliff:g>ને <xliff:g id="PERMISSION_1">%2$s</xliff:g> અને <xliff:g id="PERMISSION_2">%3$s</xliff:g>નો ઍક્સેસ આપ્યો"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"ડ્રાઇવ કરતી વખતે, તમે <xliff:g id="APP">%2$s</xliff:g>ને <xliff:g id="COUNT">%1$d</xliff:g> પરવાનગી આપી"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{ડ્રાઇવ કરતી વખતે, તમે <xliff:g id="APP_0">%1$s</xliff:g> અને અન્ય # ઍપને ઍક્સેસ આપ્યો}one{ડ્રાઇવ કરતી વખતે, તમે <xliff:g id="APP_1">%1$s</xliff:g> અને અન્ય # ઍપને ઍક્સેસ આપ્યો}other{ડ્રાઇવ કરતી વખતે, તમે <xliff:g id="APP_1">%1$s</xliff:g> અને અન્ય # ઍપને ઍક્સેસ આપ્યો}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"સેટિંગ પર જાઓ"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"અમુક ઍપનો થોડા મહિનામાં ઉપયોગ થયો નથી"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"કાઢી નાખેલી પરવાનગીઓ"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"પરવાનગીઓ કાઢી નાખી છે"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને તમારા ફોનના કૉલ લૉગ ઍક્સેસ કરવાની મંજૂરી આપીએ?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને ફોન કૉલ કરવાની અને તેને મેનેજ કરવાની મંજૂરી આપીએ?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને તમારી મહત્વપૂર્ણ સહી વિશેના સેન્સર ડેટાને ઍક્સેસ કરવાની મંજૂરી આપીએ?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"આ ઍપ તમારા જીવિત હોવાના મહત્ત્વપૂર્ણ સંકેતો વિશેનો સેન્સરનો ડેટા હંમેશાં ઍક્સેસ કરવા માગે છે, તમે ઍપ ન વાપરતા હો ત્યારે પણ. "<annotation id="link">"સેટિંગમાં મંજૂરી આપો."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"આ ઍપ તમારા આરોગ્ય વિશે મહત્ત્વપૂર્ણ સંકેતો આપતો સેન્સરનો ડેટા હંમેશાં ઍક્સેસ કરવા માગે છે, તમે ઍપ ન વાપરતા હો ત્યારે પણ. આમાં ફેરફાર કરવા માટે, "<annotation id="link">"સેટિંગ પર જાઓ."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને તમારા જીવિત હોવાના મહત્ત્વપૂર્ણ સંકેતો વિશેનો સેન્સરનો ડેટા ઍક્સેસ કરવાની મંજૂરી આપીએ?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"આ ઍપ તમારા જીવિત હોવાના મહત્ત્વપૂર્ણ સંકેતો વિશેનો સેન્સરનો ડેટા હંમેશાં ઍક્સેસ કરવા માગી શકે છે, તમે ઍપ ન વાપરતા હો ત્યારે પણ. "<annotation id="link">"સેટિંગમાં મંજૂરી આપો."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; માટે તમારા જીવિત હોવાના મહત્ત્વપૂર્ણ સંકેતો વિશેના સેન્સરના ડેટાના ઍક્સેસમાં ફેરફાર કરીએ?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"તમે ઍપનો ઉપયોગ ન પણ કરી રહ્યાં હો ત્યારે, ઍપ દરેક સમયે બૉડી સેન્સર ડેટા ઍક્સેસ કરી શકે તે માટે, "<annotation id="link">"સેટિંગ પર જાઓ."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"ઍપ ઉપયોગમાં હોય ત્યારે&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને બૉડી સેન્સર ડેટા ઍક્સેસ કરવાની મંજૂરી આપવાનું ચાલુ રાખીએ?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"શું &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને તમને નોટિફિકેશન મોકલવાની મંજૂરી આપીએ?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"શું &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને તમને નોટિફિકેશન મોકલવાનું ચાલુ રાખવાની મંજૂરી આપીએ?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"નિયંત્રિત પરવાનગીઓ"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"કૅમેરા સંબંધિત પરવાનગી કાઢી નાખો"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"માઇક્રોફોન સંબંધિત પરવાનગી કાઢી નાખો"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"સેવા મેનેજ કરો"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"પરવાનગીઓને મેનેજ કરો"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"ફોન કૉલ દ્વારા ઉપયોગ કરવામાં આવી રહ્યો છે"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"તાજેતરમાં ફોન કૉલમાં ઉપયોગ કરવામાં આવ્યો"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> દ્વારા ઉપયોગ કરવામાં આવી રહ્યો છે"</string>
diff --git a/PermissionController/res/values-hi/strings.xml b/PermissionController/res/values-hi/strings.xml
index 739d66463..63034f9ca 100644
--- a/PermissionController/res/values-hi/strings.xml
+++ b/PermissionController/res/values-hi/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"<xliff:g id="APP">%1$s</xliff:g> को मिली सभी अनुमतियां देखें"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"इस अनुमति वाले सभी ऐप्लिकेशन देखें"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"असिस्टेंट माइक्रोफ़ोन के इस्तेमाल से जुड़ा डेटा दिखाएं"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"इस्तेमाल न किए जाने वाले ऐप की सेटिंग"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"ऐप्लिकेशन का इस्तेमाल न होने पर अनुमतियां हटाएं"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"अनुमतियां हटाएं और जगह खाली करें"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"अगर इस ऐप्लिकेशन का इस्तेमाल कुछ महीनों तक नहीं किया गया, तो इसे दी गई अनुमतियां हटा दी जाएंगी. ऐसा आपके डेटा को सुरक्षित रखने के लिए किया जाएगा."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"अगर ऐप्लिकेशन कुछ महीनों से इस्तेमाल नहीं हुआ है, तो आपके डेटा को सुरक्षित रखने के लिए ये अनुमतियां हटा दी जाएंगी: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"जिन ऐप्लिकेशन का इस्तेमाल कुछ महीनों से नहीं हुआ है उन्हें दी गई अनुमतियां हटा दी गई हैं. ऐसा आपके डेटा को सुरक्षित रखने के लिए किया गया है."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"आपने गाड़ी चलाते समय, <xliff:g id="APP">%1$s</xliff:g> को <xliff:g id="PERMISSION_1">%2$s</xliff:g> और <xliff:g id="PERMISSION_2">%3$s</xliff:g> का ऐक्सेस दिया था"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"आपने गाड़ी चलाते समय, <xliff:g id="APP">%2$s</xliff:g> को <xliff:g id="COUNT">%1$d</xliff:g> अनुमतियां दी थीं"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{आपने गाड़ी चलाते समय, <xliff:g id="APP_0">%1$s</xliff:g> और # अन्य ऐप्लिकेशन को ऐक्सेस दिया था}one{आपने गाड़ी चलाते समय, <xliff:g id="APP_1">%1$s</xliff:g> और # अन्य ऐप्लिकेशन को ऐक्सेस दिया था}other{आपने गाड़ी चलाते समय, <xliff:g id="APP_1">%1$s</xliff:g> और # अन्य ऐप्लिकेशन को ऐक्सेस दिया था}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"\'सेटिंग\' पर जाएं"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"कुछ ऐप्लिकेशन का इस्तेमाल कुछ महीनों से नहीं किया गया है"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"वे ऐप्लिकेशन जिनकी अनुमतियां हटाई गई हैं"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"वे ऐप्लिकेशन जिनकी अनुमतियां हटाई गई हैं"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को अपने फ़ोन के काॅल लाॅग को ऐक्सेस करने की अनुमति देना चाहते हैं?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को फ़ोन कॉल करने और उन्हें मैनेज करने की अनुमति देना चाहते हैं?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को अपने स्वास्थ्य से जुड़ी ज़रूरी जानकारी इस्तेमाल करने की अनुमति देना चाहते हैं?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"यह ऐप्लिकेशन आपके शरीर के बारे में जानकारी देने वाले लक्षणों के सेंसर डेटा को हमेशा ऐक्सेस करने की अनुमति मांग सकता है. ऐप्लिकेशन का इस्तेमाल न किए जाने पर भी ऐसा होता है. "<annotation id="link">"सेटिंग में जाकर अनुमति दें."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"यह ऐप्लिकेशन, आपके शरीर के बारे में ज़रूरी जानकारी देने वाले सेंसर डेटा को हमेशा ऐक्सेस करने की अनुमति मांगता है. यह अनुमति उस समय के लिए भी मांगी जाती है जिस समय ऐप्लिकेशन का इस्तेमाल न हो रहा हो. यह अनुमति देने के लिए, "<annotation id="link">"सेटिंग पर जाएं."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को अपने शरीर के बारे में जानकारी देने वाले लक्षणों के सेंसर डेटा को ऐक्सेस करने की अनुमति दें?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"यह ऐप्लिकेशन आपके शरीर के बारे में जानकारी देने वाले लक्षणों के सेंसर डेटा को हमेशा ऐक्सेस करने की अनुमति मांग सकता है. ऐप्लिकेशन का इस्तेमाल न किए जाने पर भी ऐसा होता है. "<annotation id="link">"सेटिंग में जाकर अनुमति दें."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; के लिए, अपने शरीर से जुड़ी जानकारी देने वाले लक्षणों के सेंसर डेटा का ऐक्सेस बदलें?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"इस ऐप्लिकेशन का इस्तेमाल न किए जाने पर भी, इसे बॉडी सेंसर के डेटा को हमेशा ऐक्सेस करने की अनुमति देने के लिए, "<annotation id="link">"सेटिंग पर जाएं."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"क्या इस्तेमाल के दौरान, &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को बॉडी सेंसर के डेटा का ऐक्सेस देते रहना है?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को, आपको सूचनाएं भेजने की अनुमति दें?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"क्या &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को सूचनाएं भेजते रहने की अनुमति देंगें?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"कंट्रोल की गई अनुमतियां"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"कैमरा ऐक्सेस करने की अनुमति हटाई गई"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"माइक्रोफ़ोन ऐक्सेस करने की अनुमति हटाई गई"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"सेवा मैनेज करें"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"अनुमतियां मैनेज करें"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"किसी खास फ़ोन कॉल के लिए इस्तेमाल हो रहा है"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"हाल ही में, फ़ोन कॉल में इस्तेमाल किया"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> इस्तेमाल कर रहा है"</string>
diff --git a/PermissionController/res/values-hr/strings.xml b/PermissionController/res/values-hr/strings.xml
index 77db61d77..44032ae2b 100644
--- a/PermissionController/res/values-hr/strings.xml
+++ b/PermissionController/res/values-hr/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Pogledajte sva dopuštenja aplikacije <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Pogledajte sve aplikacije s tim dopuštenjem"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Prikaz korištenja mikrofona Asistenta"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Postavke nekorištene aplikacije"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Ukloni dopuštenja ako se aplikacija ne upotrebljava"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Ukloni dopuštenja i oslobodi prostor"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Kako bi se vaši podaci zaštitili, dopuštenja za ovu aplikaciju uklonit će se ako se aplikacija ne upotrebljava nekoliko mjeseci."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Kako bi se vaši podaci zaštitili, ako se aplikacija ne upotrebljava nekoliko mjeseci, uklonit će se sljedeća dopuštenja: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Radi zaštite vaših podataka uklonjena su dopuštenja aplikacijama koje nekoliko mjeseci niste upotrebljavali."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Tijekom vožnje aplikaciji <xliff:g id="APP">%1$s</xliff:g> dali ste pristup dopuštenjima <xliff:g id="PERMISSION_1">%2$s</xliff:g> i <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Tijekom vožnje dodijelili ste dopuštenja (njih <xliff:g id="COUNT">%1$d</xliff:g>) aplikaciji <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Tijekom vožnje omogućili ste pristup aplikaciji <xliff:g id="APP_0">%1$s</xliff:g> i još # aplikaciji}one{Tijekom vožnje omogućili ste pristup aplikaciji <xliff:g id="APP_1">%1$s</xliff:g> i još # aplikaciji}few{Tijekom vožnje omogućili ste pristup aplikaciji <xliff:g id="APP_1">%1$s</xliff:g> i još # aplikacije}other{Tijekom vožnje omogućili ste pristup aplikaciji <xliff:g id="APP_1">%1$s</xliff:g> i još # aplikacija}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Otvori postavke"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Neke aplikacije niste upotrebljavali nekoliko mjeseci"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Uklonjena dopuštenja"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Uklonjena dopuštenja"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa zapisnicima poziva vašeg telefona?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da upućuje telefonske pozive i upravlja njima?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa podacima senzora o vašim vitalnim znakovima?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Aplikacija želi uvijek pristupati podacima senzora o vašim vitalnim znakovima, čak i kad je ne upotrebljavate. "<annotation id="link">"Dopustite u postavkama."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Aplikacija želi uvijek pristupati podacima senzora o vašim vitalnim znakovima, čak i kad je ne upotrebljavate. Da biste unijeli tu promjenu, "<annotation id="link">"otvorite postavke"</annotation>"."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa podacima senzora o vašim vitalnim znakovima?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Ova će aplikacija možda htjeti imati pristup podacima senzora o vašim vitalnim znakovima, čak i kad je ne upotrebljavate. "<annotation id="link">"Dopustite u postavkama."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Promijeniti pristup podacima senzora o vašim vitalnim znakovima za aplikaciju &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Da biste omogućili aplikaciji da uvijek pristupa podacima s biometrijskih senzora, čak i kada je ne upotrebljavate, "<annotation id="link">"otvorite postavke."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Nastaviti dopuštati aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristup podacima s biometrijskih senzora dok je upotrebljavate?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da vam šalje obavijesti?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Želite li dopustiti aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g> da vam nastavi slati obavijesti?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Kontrolirana dopuštenja"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Ukloni dopuštenje za fotoaparat"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Ukloni dopuštenje za mikrofon"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Upravljanje uslugama"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Upravljajte dopuštenjima"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Koristi telefonski poziv"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Nedavno korišteno tijekom telefonskog poziva"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Koristi aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-hu/strings.xml b/PermissionController/res/values-hu/strings.xml
index 381e2a2cc..87f2b8347 100644
--- a/PermissionController/res/values-hu/strings.xml
+++ b/PermissionController/res/values-hu/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"A(z) <xliff:g id="APP">%1$s</xliff:g> összes engedélyének megtekintése"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Az ezzel az engedéllyel rendelkező összes alkalmazás megtekintése"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Mikrofon Segéd általi használatának megjelenítése"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Nem használt alkalmazások beállításai"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Engedélyek eltávolítása, ha nem használja az alkalmazást"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Engedélytörlés és tárhely-felszabadítás"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Az adatok védelme érdekében az ennek az alkalmazásnak adott engedélyek visszavonásra kerülnek, ha néhány hónapon át nem használja az alkalmazást."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Ha néhány hónapon át nem használja az alkalmazást, az adatok védelme érdekében a rendszer visszavonja a következő engedélyeket: <xliff:g id="PERMS">%1$s</xliff:g>."</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Az adatok védelme érdekében a rendszer eltávolította a néhány hónapja nem használt alkalmazások engedélyeit."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Vezetés közben <xliff:g id="APP">%1$s</xliff:g> alkalmazásnak <xliff:g id="PERMISSION_1">%2$s</xliff:g> és <xliff:g id="PERMISSION_2">%3$s</xliff:g>hozzáférést adott."</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Vezetés közben <xliff:g id="APP">%2$s</xliff:g> alkalmazásnak <xliff:g id="COUNT">%1$d</xliff:g> engedélyt adott"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Vezetés közben <xliff:g id="APP_0">%1$s</xliff:g> alkalmazásnak és # egyéb alkalmazásnak adott hozzáférést}other{Vezetés közben <xliff:g id="APP_1">%1$s</xliff:g> alkalmazásnak és # egyéb alkalmazásnak adott hozzáférést}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Beállítások megnyitása"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Egyes alkalmazásokat több hónapja nem használt"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Visszavont engedélyek"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Engedély visszavonva"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Engedélyezi, hogy a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; hozzáférjen az Ön hívásnaplóihoz?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára, hogy hívásokat indíthasson és kezelhessen?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára, hogy hozzáférjen az életjelekkel kapcsolatos szenzoradatokhoz?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Ez az alkalmazás akkor is hozzá szeretne férni az életjelekkel kapcsolatos szenzoradatokhoz, ha nincs használatban. "<annotation id="link">"A beállításokban engedélyezheti."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Ez az alkalmazás akkor is hozzá szeretne férni az életjelekkel kapcsolatos szenzoradatokhoz, ha nincs használatban. A módosításhoz "<annotation id="link">"lépjen a beállításokhoz."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára, hogy hozzáférjen az életjelekkel kapcsolatos szenzoradatokhoz?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Lehet, hogy az app akkor is szeretne hozzáférni az életjelekkel kapcsolatos szenzoradatokhoz, ha nincs használatban. "<annotation id="link">"A beállításokban engedélyezheti."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Engedélyezi az életjelekkel kapcsolatos szenzoradatokhoz való hozzáférést a következő számára: &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Ha engedélyezni szeretné, hogy ez az alkalmazás mindig hozzáférjen a testérzékelők adataihoz, még akkor is, amikor nem használja, "<annotation id="link">"lépjen a beállításokhoz"</annotation>"."</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Továbbra is hozzáférhessen használat közben a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; alkalmazás a testérzékelők adataihoz?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára, hogy értesítéseket küldjön Önnek?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára, hogy továbbra is küldjön értesítéseket Önnek?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Szabályozott engedélyek"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Kamera-hozzáférési engedély visszavonása"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Mikrofon-hozzáférési engedély visszavonása"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Szolgáltatás kezelése"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Engedélyek kezelése"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Jelenleg telefonhívás használja"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Legutóbb telefonhívás során volt használva"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Jelenleg a következő használja: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-hy/strings.xml b/PermissionController/res/values-hy/strings.xml
index 96d72bfcd..c53874472 100644
--- a/PermissionController/res/values-hy/strings.xml
+++ b/PermissionController/res/values-hy/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Տեսնել «<xliff:g id="APP">%1$s</xliff:g>» հավելվածի բոլոր թույլտվությունները"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Դիտել այս թույլտվությունն ունեցող հավելվածների ցանկը"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Ցույց տալ օգնականի կողմից խոսափողի օգտագործման վիճակագրությունը"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Չօգտագործվող հավելվածների կարգավորումներ"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Հեռացնել թույլտվությունները, եթե հավելվածը չի օգտագործվում"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Հեռացնել թույլտվությունները և տարածք ազատել"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Եթե հավելվածը չի օգտագործվել մի քանի ամիս, դրա թույլտվությունները կհեռացվեն՝ ձեր տվյալները պաշտպանելու համար։"</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Եթե հավելվածը չի օգտագործվել մի քանի ամիս, ձեր տվյալները պաշտպանելու համար հետևյալ թույլտվությունները կհեռացվեն՝ <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Հավելվածներից, որոնք մի քանի ամիս չեք օգտագործել, թույլտվությունները հեռացվել են՝ ձեր տվյալները պաշտպանելու համար։"</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Մեքենան վարելիս դուք <xliff:g id="APP">%1$s</xliff:g> հավելվածին տրամադրել եք <xliff:g id="PERMISSION_1">%2$s</xliff:g>ն ու <xliff:g id="PERMISSION_2">%3$s</xliff:g>ն օգտագործելու թույլտվություն"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Մեքենան վարելիս դուք <xliff:g id="COUNT">%1$d</xliff:g> թույլտվություն եք տրամադրել <xliff:g id="APP">%2$s</xliff:g> հավելվածին"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Մեքենան վարելիս դուք տրամադրել եք <xliff:g id="APP_0">%1$s</xliff:g> ու ևս # հավելվածի օգտագործման թույլտվություն}one{Մեքենան վարելիս դուք տրամադրել եք <xliff:g id="APP_1">%1$s</xliff:g> ու ևս # հավելվածի օգտագործման թույլտվություն}other{Մեքենան վարելիս դուք տրամադրել եք <xliff:g id="APP_1">%1$s</xliff:g> ու ևս # հավելվածի օգտագործման թույլտվություն}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Բացել կարգավորումները"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Որոշ հավելվածներ մի քանի ամիս է, ինչ չեն օգտագործվել"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Հավելվածներ, որոնց թույլտվությունները հեռացվել են"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Հավելվածներ, որոնց թույլտվությունները հեռացվել են"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին օգտագործել ձեր հեռախոսազանգերի մատյանները"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին կատարել հեռախոսազանգեր և կառավարել դրանք"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին սենսորից ստանալ ձեր կենսագործունեության հիմնական տվյալները:"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Հավելվածին անհրաժեշտ է մարմնի սենսորների տվյալներն օգտագործելու թույլտվություն, նույնիսկ երբ չեք օգտվում դրանից։ "<annotation id="link">"Թույլտվությունը տրամադրեք այստեղ։"</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Հավելվածին անհրաժեշտ է մարմնի սենսորների տվյալների հասանելիություն, նույնիսկ երբ չեք օգտվում դրանից։ Այս փոփոխությունը կատարելու համար "<annotation id="link">"անցեք կարգավորումներ"</annotation>"։"</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Թույլ տա՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին սենսորներից ստանալ ձեր կենսագործունեության հիմնական տվյալները։"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Հավելվածին կարող են անհրաժեշտ լինել ձեր կենսագործունեության հիմնական տվյալները, նույնիսկ երբ չեք օգտվում դրանից։ "<annotation id="link">"Թույլտվությունը տրամադրեք այստեղ։"</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Փոխե՞լ մարմնի սենսորներից կենսագործունեության տվյալներն օգտագործելու թույլտվությունը &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածի համար"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Որպեսզի այս հավելվածին հասանելի դարձնեք մարմնի սենսորների տվյալները, անգամ երբ չեք օգտվում հավելվածից, "<annotation id="link">"անցեք կարգավորումներ"</annotation>"։"</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Հասանելի դարձնե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին մարմնի սենսորների տվյալները աշխատանքի ընթացքում։"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին ծանուցումներ ուղարկել ձեզ։"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին շարունակել ծանուցումներ ուղարկել ձեզ։"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Կառավարվող թույլտվություններ"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Հեռացնել տեսախցիկի օգտագործման թույլտվությունը"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Հեռացնել խոսափողի օգտագործման թույլտվությունը"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Կառավարել ծառայությունը"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Կառավարել թույլտվությունները"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Օգտագործվում է հեռախոսազանգի ժամանակ"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Վերջերս օգտագործվել է հեռախոսազանգի ժամանակ"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Օգտագործվում է <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի կողմից"</string>
diff --git a/PermissionController/res/values-in/strings.xml b/PermissionController/res/values-in/strings.xml
index 983336986..7355bdc7c 100644
--- a/PermissionController/res/values-in/strings.xml
+++ b/PermissionController/res/values-in/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Lihat semua izin <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Lihat semua aplikasi yang memiliki izin ini"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Tampilkan penggunaan mikrofon Asisten"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Setelan aplikasi yang tidak digunakan"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Hapus izin jika aplikasi tidak digunakan"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Hapus izin &amp; kosongkan ruang penyimpanan"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Untuk melindungi data Anda, izin aplikasi ini akan dihapus jika aplikasi tidak digunakan dalam beberapa bulan."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Untuk melindungi data Anda, izin dari aplikasi yang tidak digunakan dalam beberapa bulan akan dihapus: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Untuk melindungi data Anda, izin dari aplikasi yang tidak digunakan dalam beberapa bulan telah dihapus."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Saat mengemudi, Anda memberikan akses <xliff:g id="APP">%1$s</xliff:g> ke <xliff:g id="PERMISSION_1">%2$s</xliff:g> &amp; <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Saat mengemudi, Anda memberikan <xliff:g id="COUNT">%1$d</xliff:g> izin ke <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Saat mengemudi, Anda memberikan akses ke <xliff:g id="APP_0">%1$s</xliff:g> &amp; # aplikasi lain}other{Saat mengemudi, Anda memberikan akses ke <xliff:g id="APP_1">%1$s</xliff:g> &amp; # aplikasi lain}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Buka Setelan"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Beberapa aplikasi tidak digunakan dalam beberapa bulan"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Izin yang dihapus"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Izin dihapus"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses log panggilan telepon?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; melakukan dan mengelola panggilan telepon?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses data sensor tentang tanda-tanda vital Anda?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Aplikasi ini ingin selalu mengakses data sensor tentang tanda-tanda vital Anda, meski aplikasi tidak sedang digunakan. "<annotation id="link">"Izinkan di setelan."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Aplikasi ini ingin selalu mengakses data sensor tentang tanda-tanda vital Anda, meski aplikasi tidak sedang digunakan. Untuk melakukan perubahan ini, "<annotation id="link">"buka setelan"</annotation>"."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Izinkan &lt;/b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses data sensor tentang tanda-tanda vital Anda?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Aplikasi ini mungkin ingin selalu mengakses data sensor tentang tanda-tanda vital Anda, meski aplikasi tidak sedang digunakan. "<annotation id="link">"Izinkan di setelan."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Ubah akses ke data sensor tentang tanda-tanda vital Anda untuk &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Untuk selalu mengizinkan aplikasi ini mengakses data sensor tubuh, meski saat aplikasi tidak sedang digunakan, "<annotation id="link">"buka setelan."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Terus izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses data sensor tubuh saat aplikasi sedang digunakan?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengirim notifikasi kepada Anda?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; terus mengirimi Anda notifikasi?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Izin terkontrol"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Hapus izin kamera"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Hapus izin mikrofon"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Kelola layanan"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Kelola izin"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Sedang digunakan untuk panggilan telepon"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Baru-baru ini digunakan untuk panggilan telepon"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Sedang digunakan oleh <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-is/strings.xml b/PermissionController/res/values-is/strings.xml
index a31dae99e..b146b51a3 100644
--- a/PermissionController/res/values-is/strings.xml
+++ b/PermissionController/res/values-is/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Sjá allar heimildir fyrir „<xliff:g id="APP">%1$s</xliff:g>“"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Sjá öll forrit með þessa heimild"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Sýna hljóðnemanotkun hjálpara"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Ónotaðar forritastillingar"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Fjarlægja heimildir ef forrit er ekki notað"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Fjarlægja heimildir og losa um pláss"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Til að vernda gögnin þín verða heimildir þessa forrits fjarlægðar ef það er ekki notað í nokkra mánuði."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Til að vernda gögnin þín verða eftirfarandi heimildir fjarlægðar ef forritið er ekki notað í nokkra mánuði: <xliff:g id="PERMS">%1$s</xliff:g>."</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Til að vernda gögnin þín voru heimildir fjarlægðar úr forritum sem þú hefur ekki notað í nokkra mánuði."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Þú veittir <xliff:g id="APP">%1$s</xliff:g> aðgang að <xliff:g id="PERMISSION_1">%2$s</xliff:g> og <xliff:g id="PERMISSION_2">%3$s</xliff:g> við akstur"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Þú veittir <xliff:g id="APP">%2$s</xliff:g> <xliff:g id="COUNT">%1$d</xliff:g> heimildir við akstur"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Þú veittir <xliff:g id="APP_0">%1$s</xliff:g> og # forriti í viðbót aðgang við akstur}one{Þú veittir <xliff:g id="APP_1">%1$s</xliff:g> og # forriti í viðbót aðgang við akstur}other{Þú veittir <xliff:g id="APP_1">%1$s</xliff:g> og # forritum í viðbót aðgang við akstur}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Opna stillingar"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Sum forrit hafa ekki verið notuð í nokkra mánuði"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Heimildir fjarlægðar"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Heimildir voru fjarlægðar"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Viltu veita &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aðgang að símtalaskrám símans?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Viltu leyfa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; að hringja og stjórna símtölum?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Viltu veita &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aðgang að skynjaragögnum yfir lífsmörk þín?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Þetta forrit vill fá aðgang að skynjaragögnum um lífsmörk þín hvenær sem er, líka þegar þú ert ekki að nota forritið. "<annotation id="link">"Leyfa í stillingum."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Þetta forrit vill fá stöðugan aðgang að skynjaragögnum um lífsmörk þín, líka þegar þú ert ekki að nota forritið. Ef þú vilt gera þessa breytingu skaltu "<annotation id="link">"opna stillingar."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Viltu veita &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aðgang að skynjaragögnum um lífsmörk þín?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Forritið gæti viljað fá aðgang að skynjaragögnum um lífsmörk þín hvenær sem er, líka þegar þú ert ekki að nota forritið. "<annotation id="link">"Leyfa í stillingum."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Breyta aðgangi að skynjaragögnum um lífsmörk þín fyrir &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Til að veita þessu forriti stöðugan aðgang að gögnum líkamsskynjara skaltu "<annotation id="link">"opna stillingarnar."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Veita &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aðgang að gögnum líkamsskynjara á meðan forritið er í notkun?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Leyfa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; að senda þér tilkynningar?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Leyfa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; að halda áfram að senda þér tilkynningar?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Stýrðar heimildir"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Fjarlægja myndavélarheimild"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Fjarlægja hljóðnemaheimild"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Stjórna þjónustu"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Stjórna heimildum"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Notað í símtali"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Nýlega notað í símtali"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Notað af <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-it/strings.xml b/PermissionController/res/values-it/strings.xml
index b4dae28bc..fa29f3504 100644
--- a/PermissionController/res/values-it/strings.xml
+++ b/PermissionController/res/values-it/strings.xml
@@ -61,7 +61,7 @@
<string name="auto_permission_manager_summary" msgid="9157438376234301354">"Gestisci l\'accesso ai dati relativi a calendario, registri chiamate e non solo"</string>
<string name="granted_permission_decision" msgid="7824827491551861365">"Hai consentito l\'accesso dell\'app <xliff:g id="APP_NAME">%1$s</xliff:g> a: <xliff:g id="PERMISSION_NAME">%2$s</xliff:g>"</string>
<string name="denied_permission_decision" msgid="5308961501779563781">"Hai negato l\'accesso dell\'app <xliff:g id="APP_NAME">%1$s</xliff:g> a: <xliff:g id="PERMISSION_NAME">%2$s</xliff:g>"</string>
- <string name="days_ago" msgid="6650359081551335629">"{count,plural, =0{Oggi}=1{1 giorno fa}one{# giorno fa}other{# giorni fa}}"</string>
+ <string name="days_ago" msgid="6650359081551335629">"{count,plural, =0{Oggi}=1{1 giorno fa}other{# giorni fa}}"</string>
<string name="app_disable_dlg_positive" msgid="7418444149981904940">"Disattiva app"</string>
<string name="app_disable_dlg_text" msgid="3126943217146120240">"Se disattivi questa app, Android e altre app potrebbero non funzionare più come previsto. Tieni presente che non puoi eliminare questa app perché è preinstallata sul tuo dispositivo. Puoi scegliere di disattivare l\'app e nasconderla sul tuo dispositivo."</string>
<string name="app_permission_manager" msgid="3903811137630909550">"Gestione autorizzazioni"</string>
@@ -69,7 +69,7 @@
<string name="no_permissions" msgid="3881676756371148563">"Nessuna autorizzazione"</string>
<string name="additional_permissions" msgid="5801285469338873430">"Altre autorizzazioni"</string>
<string name="app_permissions_info_button_label" msgid="7633312050729974623">"Apri informazioni sull\'app"</string>
- <string name="additional_permissions_more" msgid="5681220714755304407">"{count,plural, =1{# altra}one{# more}other{Altre #}}"</string>
+ <string name="additional_permissions_more" msgid="5681220714755304407">"{count,plural, =1{# altra}other{Altre #}}"</string>
<string name="old_sdk_deny_warning" msgid="2382236998845153919">"Questa app è stata sviluppata per una versione precedente di Android. Se l\'autorizzazione viene rifiutata, l\'app potrebbe non funzionare più come previsto."</string>
<string name="storage_supergroup_warning_allow" msgid="103093462784523190">"Questa app è stata progettata per una versione precedente di Android. Se consenti questa autorizzazione, sarà consentito l\'accesso a tutto lo spazio di archiviazione (inclusi foto, video, musica, audio e altri file)."</string>
<string name="storage_supergroup_warning_deny" msgid="6420765672683284347">"Questa app è stata progettata per una versione precedente di Android. Se neghi questa autorizzazione, sarà negato l\'accesso a tutto lo spazio di archiviazione (inclusi foto, video, musica, audio e altri file)."</string>
@@ -134,10 +134,10 @@
<string name="auto_permission_usage_timeline_summary" msgid="2713135806453218703">"<xliff:g id="ACCESS_TIME">%1$s</xliff:g> • <xliff:g id="SUMMARY_TEXT">%2$s</xliff:g>"</string>
<string name="history_preference_subtext_2" msgid="1521763591164293683">"<xliff:g id="APP_NAME">%1$s</xliff:g> • <xliff:g id="TRUNCATED_TIME">%2$s</xliff:g>"</string>
<string name="history_preference_subtext_3" msgid="758761785983094351">"<xliff:g id="ATTRIBUTION_NAME">%1$s</xliff:g> • <xliff:g id="APP_NAME">%2$s</xliff:g> • <xliff:g id="TRUNCATED_TIME">%3$s</xliff:g>"</string>
- <string name="duration_used_days" msgid="8293010131040301793">"{count,plural, =1{1 giorno}one{# giorno}other{# giorni}}"</string>
- <string name="duration_used_hours" msgid="1128716208752263576">"{count,plural, =1{1 ora}one{# ora}other{# ore}}"</string>
- <string name="duration_used_minutes" msgid="5335824115042576567">"{count,plural, =1{1 min}one{# min}other{# min}}"</string>
- <string name="duration_used_seconds" msgid="6543746449171675028">"{count,plural, =1{1 sec}one{# sec}other{# sec}}"</string>
+ <string name="duration_used_days" msgid="8293010131040301793">"{count,plural, =1{1 giorno}other{# giorni}}"</string>
+ <string name="duration_used_hours" msgid="1128716208752263576">"{count,plural, =1{1 ora}other{# ore}}"</string>
+ <string name="duration_used_minutes" msgid="5335824115042576567">"{count,plural, =1{1 min}other{# min}}"</string>
+ <string name="duration_used_seconds" msgid="6543746449171675028">"{count,plural, =1{1 sec}other{# sec}}"</string>
<string name="permission_usage_any_permission" msgid="6358023078298106997">"Qualsiasi autorizzazione"</string>
<string name="permission_usage_any_time" msgid="3802087027301631827">"Qualsiasi data"</string>
<string name="permission_usage_last_7_days" msgid="7386221251886130065">"Ultimi 7 giorni"</string>
@@ -160,7 +160,7 @@
<string name="permission_usage_bar_chart_title_last_minute" msgid="820450867183487607">"Uso autorizzazioni nell\'ultimo minuto"</string>
<string name="permission_usage_preference_summary_not_used_24h" msgid="3087783232178611025">"Autorizzazione non utilizzata nelle ultime 24 ore"</string>
<string name="permission_usage_preference_summary_not_used_7d" msgid="4592301300810120096">"Autorizzazione non utilizzata negli ultimi 7 giorni"</string>
- <string name="permission_usage_preference_label" msgid="8343167938128676378">"{count,plural, =1{Utilizzate da 1 app}one{Utilizzate da # app}other{Utilizzate da # app}}"</string>
+ <string name="permission_usage_preference_label" msgid="8343167938128676378">"{count,plural, =1{Utilizzate da 1 app}other{Utilizzate da # app}}"</string>
<string name="permission_usage_view_details" msgid="6675335735468752787">"Mostra tutto nella Dashboard"</string>
<string name="app_permission_usage_filter_label" msgid="7182861154638631550">"Filtrata per: <xliff:g id="PERM">%1$s</xliff:g>"</string>
<string name="app_permission_usage_remove_filter" msgid="2926157607436428207">"Rimuovi filtro"</string>
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Mostra tutte le autorizzazioni di <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Mostra tutte le app con questa autorizzazione"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Mostra utilizzo microfono dell\'assistente"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Impostazioni app inutilizzate"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Rimuovi autorizzazioni se non in uso"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Rimuovi autorizzazioni e libera spazio"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Per proteggere i tuoi dati, le autorizzazioni di questa app verranno rimosse se l\'app non viene usata per alcuni mesi."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Per proteggere i tuoi dati, se l\'app non viene usata per alcuni mesi, le seguenti autorizzazioni verranno rimosse: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Per proteggere i tuoi dati, sono state rimosse le autorizzazioni dalle app che non hai utilizzato per alcuni mesi."</string>
@@ -247,25 +252,24 @@
<string name="denied_header" msgid="903209608358177654">"Autorizzazione non concessa"</string>
<string name="storage_footer_warning_text" msgid="2242258357752432337">"Alcune app che forniscono funzionalità essenziali per il dispositivo potrebbero avere un accesso speciale a tutti i file"</string>
<string name="storage_footer_hyperlink_text" msgid="7759955324552930974">"Visualizza le app con accesso a tutti i file"</string>
- <string name="days" msgid="609563020985571393">"{count,plural, =1{1 giorno}one{# giorno}other{# giorni}}"</string>
- <string name="hours" msgid="3447767892295843282">"{count,plural, =1{1 ora}one{# ora}other{# ore}}"</string>
- <string name="minutes" msgid="4408293038068503157">"{count,plural, =1{1 minuto}one{# minuto}other{# minuti}}"</string>
- <string name="seconds" msgid="5397771912131132690">"{count,plural, =1{1 secondo}one{# secondo}other{# secondi}}"</string>
+ <string name="days" msgid="609563020985571393">"{count,plural, =1{1 giorno}other{# giorni}}"</string>
+ <string name="hours" msgid="3447767892295843282">"{count,plural, =1{1 ora}other{# ore}}"</string>
+ <string name="minutes" msgid="4408293038068503157">"{count,plural, =1{1 minuto}other{# minuti}}"</string>
+ <string name="seconds" msgid="5397771912131132690">"{count,plural, =1{1 secondo}other{# secondi}}"</string>
<string name="permission_reminders" msgid="6528257957664832636">"Promemoria autorizzazione"</string>
<string name="auto_revoke_permission_reminder_notification_title_one" msgid="6690347469376854137">"1 app inutilizzata"</string>
<string name="auto_revoke_permission_reminder_notification_title_many" msgid="6062217713645069960">"<xliff:g id="NUMBER_OF_APPS">%s</xliff:g> app inutilizzate"</string>
<string name="auto_revoke_permission_reminder_notification_content" msgid="4492228990462107487">"Autorizzazioni rimosse per proteggere la tua privacy. Tocca per controllare"</string>
<string name="auto_revoke_permission_notification_title" msgid="2629844160853454657">"Autorizzazioni rimosse per le app inutilizzate"</string>
<string name="auto_revoke_permission_notification_content" msgid="5125990886047799375">"Alcune app non sono state usate per alcuni mesi. Tocca per controllare."</string>
- <string name="unused_apps_notification_title" msgid="4314832015894238019">"{count,plural, =1{# app inutilizzata}one{# app inutilizzata}other{# app inutilizzate}}"</string>
+ <string name="unused_apps_notification_title" msgid="4314832015894238019">"{count,plural, =1{# app inutilizzata}other{# app inutilizzate}}"</string>
<string name="unused_apps_notification_content" msgid="9195026773244581246">"Le autorizzazioni e i file temporanei sono stati rimossi; le notifiche sono state interrotte. Tocca per controllare."</string>
<string name="post_drive_permission_decision_reminder_title" msgid="1290697371418139976">"Controlla le autorizzazioni recenti"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_1_permission" msgid="670521503734140711">"Durante la guida, hai consentito all\'app <xliff:g id="APP">%1$s</xliff:g> di accedere a <xliff:g id="PERMISSION">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Durante la guida, hai consentito all\'app <xliff:g id="APP">%1$s</xliff:g> di accedere a <xliff:g id="PERMISSION_1">%2$s</xliff:g> e <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Durante la guida, hai concesso <xliff:g id="COUNT">%1$d</xliff:g> autorizzazioni all\'app <xliff:g id="APP">%2$s</xliff:g>"</string>
- <string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Durante la guida, hai consentito l\'accesso a <xliff:g id="APP_0">%1$s</xliff:g> e a # altra app}one{Durante la guida, hai consentito l\'accesso a <xliff:g id="APP_1">%1$s</xliff:g> e a # altra app}other{Durante la guida, hai consentito l\'accesso a <xliff:g id="APP_1">%1$s</xliff:g> e ad altre # app}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Durante la guida, hai consentito l\'accesso a <xliff:g id="APP_0">%1$s</xliff:g> e a # altra app}other{Durante la guida, hai consentito l\'accesso a <xliff:g id="APP_1">%1$s</xliff:g> e ad altre # app}}"</string>
+ <string name="go_to_settings" msgid="1053735612211228335">"Vai a Impostazioni"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Alcune app non sono state usate per alcuni mesi"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Autorizzazioni rimosse"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Autorizzazioni rimosse"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere ai registri chiamate del tuo telefono?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di effettuare e gestire telefonate?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Consentire a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere ai dati dei sensori relativi ai parametri vitali?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Questa app vuole accedere sempre ai dati dei sensori relativi ai parametri vitali, anche quando non la usi. "<annotation id="link">"Consenti l\'accesso nelle impostazioni."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Questa app vuole sempre accedere ai dati dei sensori dei parametri vitali, anche quando non la usi. Per apportare questa modifica, "<annotation id="link">"vai alle impostazioni."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere ai dati dei sensori relativi ai parametri vitali?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Questa app potrebbe voler accedere sempre ai dati dei sensori relativi ai parametri vitali, anche quando non la usi. "<annotation id="link">"Consenti accesso in impostazioni."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Cambiare l\'accesso ai dati dei sensori relativi ai parametri vitali per &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Per autorizzare l\'app ad accedere ai dati relativi ai sensori del corpo sempre, anche mentre non utilizzi l\'app, "<annotation id="link">"vai alle impostazioni."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Continuare ad autorizzare &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ad accedere ai dati relativi ai sensori del corpo mentre l\'app è in uso?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Vuoi consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di inviarti notifiche?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Vuoi consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di continuare a inviarti notifiche?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Autorizzazioni controllate"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Rimuovi autorizzazione di accesso alla fotocamera"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Rimuovi autorizzazione di accesso al microfono"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Gestisci servizio"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Gestire le autorizzazioni"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Attualmente in uso per la telefonata"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Recentemente in uso nella telefonata"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Attualmente in uso per <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-iw/strings.xml b/PermissionController/res/values-iw/strings.xml
index e2c49e135..f6d120eab 100644
--- a/PermissionController/res/values-iw/strings.xml
+++ b/PermissionController/res/values-iw/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"הצגת כל ההרשאות של \'<xliff:g id="APP">%1$s</xliff:g>\'"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"הצגת כל האפליקציות עם ההרשאה הזו"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"‏הצגת השימוש במיקרופון של Assistant"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"הגדרות של אפליקציות שמזמן לא השתמשת בהן"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"הסרת ההרשאות כשלא בשימוש"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"הסרת הרשאות ופינוי מקום אחסון"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"כדי להגן על הנתונים שלך, אם האפליקציה הזו לא תהיה בשימוש במשך מספר חודשים, ההרשאות שניתנו לה יוסרו."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"כדי להגן על הנתונים שלך, אם האפליקציה לא תהיה בשימוש במשך מספר חודשים, ההרשאות הבאות יוסרו: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"כדי להגן על הנתונים שלך, הוסרו הרשאות מאפליקציות שלא השתמשת בהן במשך מספר חודשים."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"במהלך הנהיגה, נתת לאפליקציה <xliff:g id="APP">%1$s</xliff:g> גישה ל<xliff:g id="PERMISSION_1">%2$s</xliff:g> ול<xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"במהלך הנהיגה, הענקת <xliff:g id="COUNT">%1$d</xliff:g> הרשאות לאפליקציה <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{במהלך הנהיגה, נתת גישה לאפליקציה <xliff:g id="APP_0">%1$s</xliff:g> ולאפליקציה אחת נוספת}two{במהלך הנהיגה, נתת גישה לאפליקציה <xliff:g id="APP_1">%1$s</xliff:g> ול-# אפליקציות נוספות}many{במהלך הנהיגה, נתת גישה לאפליקציה <xliff:g id="APP_1">%1$s</xliff:g> ול-# אפליקציות נוספות}other{במהלך הנהיגה, נתת גישה לאפליקציה <xliff:g id="APP_1">%1$s</xliff:g> ול-# אפליקציות נוספות}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"להגדרות"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"יש אפליקציות שלא נעשה בהן שימוש כבר כמה חודשים"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"ההרשאות שהוסרו"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"הוסרו הרשאות"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאת גישה ליומני השיחות של הטלפון?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאה לבצע ולנהל שיחות טלפון?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאת גישה לנתוני חיישנים העוקבים אחר הסימנים החיוניים שלך?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"האפליקציה הזו מבקשת לקבל גישה לנתוני החיישנים המודדים את הסימנים החיוניים שלך כל הזמן, גם כשהיא לא בשימוש. "<annotation id="link">"יש לך אפשרות לאשר זאת בהגדרות."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"האפליקציה הזו מבקשת הרשאת גישה לנתוני החיישנים שמודדים את הסימנים החיוניים שלך כל הזמן, גם כשלא נעשה בה שימוש. כדי לשנות את ההגדרה הזו, "<annotation id="link">"צריך לעבור להגדרות"</annotation>"."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"‏להעניק לאפליקציה &lt;b‏/&gt;‏<xliff:g id="APP_NAME">%1$s</xliff:g>‏&lt;b&gt; הרשאת גישה לנתוני החיישנים שמודדים את הסימנים החיוניים שלך?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"יכול להיות שהאפליקציה תבקש לגשת לנתוני החיישנים המודדים את הסימנים החיוניים שלך כל הזמן, גם כשהיא לא בשימוש. "<annotation id="link">"יש לך אפשרות לאשר זאת בהגדרות."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"‏לשנות את הרשאת הגישה של &lt;b‏/&gt;‏<xliff:g id="APP_NAME">%1$s</xliff:g>‏&lt;b&gt; לנתוני החיישנים המודדים את הסימנים החיוניים שלך?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"כדי לאפשר לאפליקציה הזו לגשת לנתונים של חיישנים גופניים כל הזמן, גם כשהיא לא בשימוש, "<annotation id="link">"צריך להיכנס להגדרות."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"‏להמשיך לאפשר לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; לגשת לנתונים של חיישנים גופניים כשהיא נמצאת בשימוש?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאה לשלוח לך התראות?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאה להמשיך לשלוח לך התראות?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"הרשאות בבקרה"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"הסרה של הרשאת הגישה למצלמה"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"הסרה של הרשאת הגישה למיקרופון"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"ניהול השירות"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"ניהול הרשאות"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"בשימוש על ידי שיחת טלפון"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"נעשה שימוש לאחרונה על ידי שיחת טלפון"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"בשימוש על ידי <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-ja/strings.xml b/PermissionController/res/values-ja/strings.xml
index f4821787b..b0db0f206 100644
--- a/PermissionController/res/values-ja/strings.xml
+++ b/PermissionController/res/values-ja/strings.xml
@@ -196,8 +196,11 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"「<xliff:g id="APP">%1$s</xliff:g>」アプリの権限をすべて表示"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"この権限があるアプリをすべて表示"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"アシスタントのマイクの使用を表示"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"使用されていないアプリの設定"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"アプリが使用されていない場合に権限を削除"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"権限を削除して空き容量を増やす"</string>
+ <string name="unused_apps_label_v2" msgid="7058776770056517980">"使用していないアプリを一時停止する"</string>
+ <string name="unused_apps_summary" msgid="8839466950318403115">"権限と一時ファイルを削除し、通知を停止します"</string>
<string name="auto_revoke_summary" msgid="5867548789805911683">"データ保護のため、このアプリが数か月使用されていない場合はアプリの権限が取り消されます。"</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"データ保護のため、アプリが数か月使用されていない場合は以下の権限が取り消されます。<xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"データ保護のため、数か月使用していないアプリの権限を削除しました。"</string>
@@ -264,8 +267,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"運転中に <xliff:g id="APP">%1$s</xliff:g> による<xliff:g id="PERMISSION_1">%2$s</xliff:g>および<xliff:g id="PERMISSION_2">%3$s</xliff:g>へのアクセスを許可しました"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"運転中に <xliff:g id="APP">%2$s</xliff:g> に権限を <xliff:g id="COUNT">%1$d</xliff:g> 回許可しました"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{運転中に <xliff:g id="APP_0">%1$s</xliff:g> およびその他のアプリによるアクセスを許可しました}other{運転中に <xliff:g id="APP_1">%1$s</xliff:g> およびその他 # 個のアプリによるアクセスを許可しました}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"設定に移動"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"数か月使用していないアプリがあります"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"削除された権限"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"削除済みの権限"</string>
@@ -468,10 +470,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"通話履歴へのアクセスを「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」に許可しますか?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"電話の発信と管理を「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」に許可しますか?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"バイタルサインに関するセンサーデータへのアクセスを「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」に許可しますか?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"このアプリは、未使用時も含め、常にバイタルサインに関するセンサーデータへのアクセスを試みます。"<annotation id="link">"設定で許可してください。"</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"このアプリは、未使用時も含め、常にバイタルサインに関するセンサーデータへのアクセスを試みます。これを変更するには、"<annotation id="link">"設定に移動"</annotation>"してください。"</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"バイタルサインに関するセンサーデータへのアクセスを &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"このアプリは、未使用時も含め、常にバイタルサインに関するセンサーデータへのアクセスを試みる可能性があります。"<annotation id="link">"設定で許可してください。"</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; のバイタルサインに関するセンサーデータへのアクセス権限を変更しますか?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"アプリの未使用時も、常にボディセンサー データにアクセスすることをこのアプリに許可するには、"<annotation id="link">"設定に移動"</annotation>"してください。"</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"ボディセンサー データへのアクセスを、引き続きアプリの使用時のみ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"通知の送信を &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"通知を引き続き送信することを &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"権限は管理されています"</string>
@@ -509,6 +511,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"カメラの権限を削除"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"マイクの権限を削除"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"サービスを管理"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"権限の管理"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"通話が使用中"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"通話で最近使用"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> が使用中"</string>
diff --git a/PermissionController/res/values-ka/strings.xml b/PermissionController/res/values-ka/strings.xml
index 6acaeceea..7b0431dcd 100644
--- a/PermissionController/res/values-ka/strings.xml
+++ b/PermissionController/res/values-ka/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"ყველა ნებართვის ნახვა: <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"ამ ნებართვის მქონე ყველა აპის ნახვა"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"ასისტენტის მიკროფონის გამოყენების ჩვენება"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"აპის გამოუყენებელი პარამეტრები"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"ნებართვების ამოშლა აპის გამოუყენებლობის შემთხვევაში."</string>
<string name="unused_apps_label" msgid="2595428768404901064">"ნებართვების ამოშლა და მეხსიერების გათავისუფლება"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"თქვენი მონაცემების დასაცავად ნებართვები ამოიშლება ამ აპიდან, თუ ის რამდენიმე თვის განმავლობაში არ გამოგიყენებიათ."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"თქვენი მონაცემების დაცვის მიზნით, თუ აპს რამდენიმე თვის განმავლობაში არ გამოიყენებთ, ამოიშლება შემდეგი ნებართვები: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"თქვენი მონაცემების დასაცავად ნებართვები ამოიშალა აპებიდან, რომლებიც რამდენიმე თვის განმავლობაში არ გამოგიყენებიათ."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"მანქანის მართვის დროს <xliff:g id="APP">%1$s</xliff:g>-ს წვდომა მიეცით ამ ნებართვებზე: <xliff:g id="PERMISSION_1">%2$s</xliff:g> და <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"მანქანის მართვის დროს თქვენ <xliff:g id="COUNT">%1$d</xliff:g> ნებართვა დაუშვით <xliff:g id="APP">%2$s</xliff:g>-ზე"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{მანქანის მართვის დროს <xliff:g id="APP_0">%1$s</xliff:g>-სა და # სხვა აპს მიეცით ნებართვა}other{მანქანის მართვის დროს <xliff:g id="APP_1">%1$s</xliff:g>-სა და # სხვა აპს მიეცით ნებართვა}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"პარამეტრებზე გადასვლა"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"ზოგიერთი აპი რამდენიმე თვეა გამოუყენებელია"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"გაუქმებული ნებართვები"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"ნებართვები გაუქმდა"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-ს თქვენს ზარების ჟურნალებზე წვდომის ნებართვა?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ს&lt;/b&gt; სატელეფონო ზარების განხორციელების და მართვის ნებართვა?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ს&lt;/b&gt; თქვენი სასიცოცხლო ფუნქციების შესახებ სენსორის მონაცემებზე წვდომის ნებართვა?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"ეს აპი ითხოვს თქვენი სასიცოც. ფუნქციების შესახებ სენსორის მონაცემებზე წვდომას ნებისმიერ დროს, მაშინაც კი, როცა მას არ იყენებთ. "<annotation id="link">"დაუშვით პარამეტრებიდან."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"ეს აპი ითხოვს თქვენი სასიცოცხლო ფუნქციების შესახებ სენსორის მონაცემებზე წვდომას ნებისმიერ დროს, მაშინაც კი, როცა აპს არ იყენებთ. ამ ცვლილებისთვის "<annotation id="link">"გადადით პარამეტრებზე."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-ს თქვენი სასიცოცხლო ფუნქციების შესახებ სენსორის მონაცემებზე წვდომის ნებართვა?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"ამ აპს შეუძლია თქვენი სასიცოც. ფუნქციების შესახებ სენსორის მონაცემებზე წვდომა ნებისმიერ დროს, მაშინაც კი, როცა აპს არ იყენებთ. "<annotation id="link">"დაუშვით პარამეტრებიდან."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"გსურთ თქვენი სასიცოცხლო ფუნქციების შესახებ სენსორის მონაცემებზე წვდომა შეცვალოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-ისთვის?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"ამ აპისთვის სხეულის სენსორების მონაცემებზე მუდმივი წვდომის მისანიჭებლად (მაშინაც კი, როცა აპს არ იყენებთ), "<annotation id="link">"გადადით პარამეტრებზე."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"გსურთ გამოყენებისას &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-ს მიანიჭოთ სხეულის სენსორების მონაცემებზე წვდომა?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"მისცემთ უფლებას &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-ს, გამოგიგზავნოთ შეტყობინებები?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"მისცემთ უფლებას &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-ს, განაგრძოს თქვენთვის შეტყობინებების გამოგზავნა?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"კონტროლირებული ნებართვები"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"კამერის ნებართვის ამოშლა"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"მიკროფონის ნებართვის ამოშლა"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"სერვისის მართვა"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"ნებართვების მართვა"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"ამჟამად იყენებს სატელეფონო ზარი"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"ახლახან გამოყენებულია სატელეფონო ზარის მიერ"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"ამჟამად იყენებს <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-kk/strings.xml b/PermissionController/res/values-kk/strings.xml
index 0af845db3..8d7294f4e 100644
--- a/PermissionController/res/values-kk/strings.xml
+++ b/PermissionController/res/values-kk/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Барлық <xliff:g id="APP">%1$s</xliff:g> рұқсаттарын көру"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Осы рұқсатқа ие барлық қолданбаларды көру"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Assistant микрофонының пайдаланылуын көрсету"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Пайдаланылмайтын қолданба параметрлері"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Қолданба пайдаланылмаса, рұқсаттарды өшіру"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Рұқсаттарды өшіру және орын босату"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Бұл қолданба бірнеше ай бойы пайдаланылмаса, деректеріңізді қорғау үшін оған берілген рұқсаттар өшіріледі."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Қолданба бірнеше ай бойы пайдаланылмаса, деректеріңізді қорғау үшін мына рұқсаттар өшіріледі: <xliff:g id="PERMS">%1$s</xliff:g>."</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Бірнеше ай бойы пайдаланылмаған қолданбаларға берілген рұқсаттар деректеріңізді қорғау үшін өшірілді."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Көлік жүргізген кезде, <xliff:g id="APP">%1$s</xliff:g> қолданбасына <xliff:g id="PERMISSION_1">%2$s</xliff:g> және <xliff:g id="PERMISSION_2">%3$s</xliff:g> рұқсаттарын бердіңіз."</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Көлік жүргізген кезде, <xliff:g id="APP">%2$s</xliff:g> қолданбасына <xliff:g id="COUNT">%1$d</xliff:g> рұқсат бердіңіз."</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Көлік жүргізген кезде, <xliff:g id="APP_0">%1$s</xliff:g> және басқа # қолданбаға рұқсат бердіңіз.}other{Көлік жүргізген кезде, <xliff:g id="APP_1">%1$s</xliff:g> және басқа # қолданбаға рұқсат бердіңіз.}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Параметрлерге өту"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Кейбір қолданбалар бірнеше ай бойы пайдаланылмаған."</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Өшірілген рұқсаттар"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Рұқсаттары өшірілген"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына телефонның қоңыраулар журналына кіруге рұқсат берілсін бе?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына қоңырау шалуға және қоңырауларды басқаруға рұқсат берілсін бе?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына негізгі физиологиялық көрсеткіштерді көрсететін сенсорлық деректерді пайдалануға рұқсат берілсін бе?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Қолданбаны пайдаланбасаңыз да, ол үнемі датчик деректерін пайдаланғысы келеді. "<annotation id="link">"Параметрлерден рұқсат беріңіз."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Қолданбаны пайдаланбасаңыз да, ол әрдайым тіршілік көрсеткіштері туралы датчик дерегін пайдалануға рұқсат сұрайды. Мұны өзгерту үшін "<annotation id="link">"параметрлерге өтіңіз."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына тіршілік көрсеткіштеріне қатысты датчик деректерін пайдалануға рұқсат берілсін бе?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Қолданбаны пайдаланбасаңыз да, ол үнемі датчик деректерін пайдаланғысы келуі мүмкін. "<annotation id="link">"Параметрлерден рұқсат беріңіз."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Тіршілік көрсеткіштеріне қатысты датчик деректерін &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасының пайдалану жолы өзгертілсін бе?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Бұл қолданбаға кез келген уақытта (ол пайдаланылмаған кезде де) дене датчигінен алынған деректі пайдалануға рұқсат беру үшін "<annotation id="link">"параметрлерге өтіңіз."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Жұмыс кезінде &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасы дене датчигінен алынған деректі одан әрі пайдалана берсін бе?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасы хабарландыру жіберсін бе?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасы хабарландыру жібере берсін бе?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Басқарылатын рұқсаттар"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Камера пайдалану рұқсатын өшіру"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Микрофон пайдалану рұқсатын өшіру"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Қызметті басқару"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Рұқсаттарды басқару"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Телефон қоңырауы үшін пайдаланылуда."</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Соңғы рет телефон қоңырауы үшін пайдаланылды."</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> пайдалануда."</string>
diff --git a/PermissionController/res/values-km/strings.xml b/PermissionController/res/values-km/strings.xml
index b9aba241d..bb24d2a66 100644
--- a/PermissionController/res/values-km/strings.xml
+++ b/PermissionController/res/values-km/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"មើល​ការអនុញ្ញាតទាំងអស់ឱ្យទៅ <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"មើលកម្មវិធី​ទាំងអស់​ដែលមាន​ការអនុញ្ញាត​នេះ"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"បង្ហាញការប្រើប្រាស់​មីក្រូហ្វូនរបស់ជំនួយការ"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"ការកំណត់កម្មវិធីដែលមិនប្រើ"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"ដកការ​អនុញ្ញាតចេញ ប្រសិនបើ​មិនប្រើប្រាស់​កម្មវិធី"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"ដក​ការអនុញ្ញាតចេញ និងបង្កើន​ទំហំផ្ទុក"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"ដើម្បីការពារ​ទិន្នន័យរបស់អ្នក ការអនុញ្ញាត​សម្រាប់កម្មវិធីនេះ​នឹងត្រូវ​ដកចេញ ប្រសិនបើ​មិនប្រើប្រាស់​កម្មវិធីនេះ​រយៈពេល​ពីរបីខែ។"</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"ដើម្បីការពារ​ទិន្នន័យរបស់អ្នក ការអនុញ្ញាត​ខាងក្រោម​នឹងត្រូវដកចេញ ប្រសិនបើ​មិនប្រើប្រាស់​កម្មវិធីនេះ​រយៈពេល​ពីរបីខែ៖ <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"ដើម្បីការពារ​ទិន្នន័យរបស់អ្នក ការអនុញ្ញាត​ត្រូវបាន​ដកចេញ​ពីកម្មវិធី​ដែល​អ្នកមិនបាន​ប្រើប្រាស់​រយៈពេល​ពីរបីខែ។"</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"នៅពេល​បើកបរ អ្នកបានផ្ដល់​សិទ្ធិចូលប្រើ <xliff:g id="PERMISSION_1">%2$s</xliff:g> និង <xliff:g id="PERMISSION_2">%3$s</xliff:g> ដល់ <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"នៅពេល​បើកបរ អ្នកបានផ្ដល់​សិទ្ធិចូលប្រើ​ចំនួន <xliff:g id="COUNT">%1$d</xliff:g> ដល់ <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{នៅពេល​បើកបរ អ្នកបានផ្ដល់​សិទ្ធិចូលប្រើដល់ <xliff:g id="APP_0">%1$s</xliff:g> និង​កម្មវិធី # ទៀត}other{នៅពេល​បើកបរ អ្នកបានផ្ដល់​សិទ្ធិចូលប្រើដល់ <xliff:g id="APP_1">%1$s</xliff:g> និង​កម្មវិធី # ទៀត}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"ចូលទៅការកំណត់"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"កម្មវិធី​មួយចំនួន​មិនត្រូវបាន​ប្រើប្រាស់​រយៈពេល​ពីរបីខែ​ហើយ"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"ការអនុញ្ញាត​ដែលបានដក"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"បានដក​ការអនុញ្ញាត"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"អនុញ្ញាត​ឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូល​ប្រើ​កំណត់ហេតុ​ហៅទូរសព្ទ​របស់អ្នក?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; គ្រប់គ្រង និង​ធ្វើការហៅទូរសព្ទ?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូលប្រើ​ទិន្នន័យឧបករណ៍ចាប់សញ្ញាអំពីស្ថានភាពសុខភាពរបស់អ្នក?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"កម្មវិធីនេះចង់ចូលប្រើទិន្នន័យឧបករណ៍ចាប់សញ្ញាអំពីស្ថានភាពសុខភាពរបស់អ្នកគ្រប់ពេល ទោះបីជានៅពេលអ្នកមិនកំពុងប្រើកម្មវិធីនេះក៏ដោយ។ "<annotation id="link">"អនុញ្ញាតនៅក្នុងការកំណត់។"</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"កម្មវិធីនេះចង់ចូលប្រើទិន្នន័យឧបករណ៍ចាប់សញ្ញាអំពីស្ថានភាពសុខភាពរបស់អ្នកគ្រប់ពេល ទោះបីជានៅពេលអ្នកមិនកំពុងប្រើកម្មវិធីនេះក៏ដោយ។ ដើម្បីធ្វើការផ្លាស់ប្ដូរនេះ សូម"<annotation id="link">"ចូលទៅកាន់ការកំណត់។"</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូលប្រើទិន្នន័យ​ឧបករណ៍ចាប់សញ្ញា​អំពីស្ថានភាពសុខភាព​របស់អ្នកឬ?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"កម្មវិធីនេះប្រហែលជាចង់ចូលប្រើទិន្នន័យឧបករណ៍ចាប់សញ្ញាអំពីស្ថានភាពសុខភាពរបស់អ្នកគ្រប់ពេល ទោះបីជានៅពេលអ្នកមិនកំពុងប្រើកម្មវិធីនេះក៏ដោយ។ "<annotation id="link">"អនុញ្ញាតនៅក្នុងការកំណត់។"</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"ប្ដូរសិទ្ធិចូលប្រើទិន្នន័យឧបករណ៍​ចាប់សញ្ញាអំពី​ស្ថានភាពសុខភាព​របស់អ្នកសម្រាប់ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ឬ?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"ដើម្បីអនុញ្ញាតឱ្យកម្មវិធីនេះចូលប្រើទិន្នន័យឧបករណ៍ចាប់សញ្ញារាងកាយគ្រប់ពេល ទោះបីជានៅពេលអ្នកមិនកំពុងប្រើកម្មវិធីនេះក៏ដោយ សូម"<annotation id="link">"ចូលទៅកាន់ការកំណត់។"</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"បន្តអនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូលប្រើទិន្នន័យឧបករណ៍ចាប់សញ្ញារាងកាយ ខណៈពេលកំពុងប្រើកម្មវិធីឬ?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ផ្ញើ​ការជូនដំណឹង​ឱ្យអ្នកឬ?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; បន្តផ្ញើការជូនដំណឹងឱ្យអ្នកឬ?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"ការអនុញ្ញាត​ដែលស្ថិតក្រោម​ការគ្រប់គ្រង"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"ដកការអនុញ្ញាតកាមេរ៉ា"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"ដកការអនុញ្ញាតមីក្រូហ្វូន"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"គ្រប់គ្រង​សេវាកម្ម"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"គ្រប់គ្រង​ការអនុញ្ញាត"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"កំពុងប្រើដោយការហៅទូរសព្ទ"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"បានប្រើនាពេលថ្មីៗនេះនៅក្នុងការហៅទូរសព្ទ"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"កំពុងប្រើដោយ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-kn/strings.xml b/PermissionController/res/values-kn/strings.xml
index 9200c628c..f740ed9e5 100644
--- a/PermissionController/res/values-kn/strings.xml
+++ b/PermissionController/res/values-kn/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"ಎಲ್ಲಾ <xliff:g id="APP">%1$s</xliff:g> ಅನುಮತಿಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"ಈ ಅನುಮತಿಯನ್ನು ಹೊಂದಿರುವ ಎಲ್ಲಾ ಆ್ಯಪ್‌ಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"ಅಸಿಸ್ಟೆಂಟ್‌ನ ಮೈಕ್ರೋಫೋನ್ ಬಳಕೆಯನ್ನು ತೋರಿಸಿ"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"ಬಳಕೆಯಾಗದಿರುವ ಆ್ಯಪ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"ಆ್ಯಪ್‌ ಬಳಸದಿದ್ದರೆ ಅನುಮತಿಗಳನ್ನು ತೆಗೆದುಹಾಕಿ"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"ಅನುಮತಿಗಳನ್ನು ತೆಗೆಯಿರಿ, ಸ್ಥಳ ಮುಕ್ತಗೊಳಿಸಿ"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"ಆ್ಯಪ್ ಅನ್ನು ಕೆಲವು ತಿಂಗಳುಗಳ ಕಾಲ ಬಳಸದಿದ್ದರೆ, ನಿಮ್ಮ ಡೇಟಾವನ್ನು ರಕ್ಷಿಸಲು ಈ ಆ್ಯಪ್‌ನ ಅನುಮತಿಗಳನ್ನು ತೆಗೆದುಹಾಕಲಾಗುವುದು."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"ಆ್ಯಪ್ ಅನ್ನು ಕೆಲವು ತಿಂಗಳುಗಳ ಕಾಲ ಬಳಸದಿದ್ದರೆ, ನಿಮ್ಮ ಡೇಟಾವನ್ನು ರಕ್ಷಿಸಲು, ಈ ಕೆಳಗಿನ ಅನುಮತಿಗಳನ್ನು ತೆಗೆದುಹಾಕಲಾಗುವುದು: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"ನಿಮ್ಮ ಡೇಟಾವನ್ನು ರಕ್ಷಿಸಲು, ಕೆಲವು ತಿಂಗಳುಗಳಿಂದ ನೀವು ಬಳಸದಿರುವ ಆ್ಯಪ್‌ಗಳಿಂದ ಅನುಮತಿಗಳನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"ನೀವು ವಾಹನ ಚಲಾಯಿಸುವಾಗ, <xliff:g id="APP">%1$s</xliff:g> ಗೆ <xliff:g id="PERMISSION_1">%2$s</xliff:g> ಮತ್ತು <xliff:g id="PERMISSION_2">%3$s</xliff:g> ಪ್ರವೇಶವನ್ನು ನೀಡಿದ್ದೀರಿ"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"ನೀವು ವಾಹನ ಚಲಾಯಿಸುವಾಗ, <xliff:g id="APP">%2$s</xliff:g> ಗೆ <xliff:g id="COUNT">%1$d</xliff:g> ಅನುಮತಿಗಳನ್ನು ನೀಡಿದ್ದೀರಿ"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{ನೀವು ವಾಹನ ಚಲಾಯಿಸುವಾಗ, <xliff:g id="APP_0">%1$s</xliff:g> ಮತ್ತು # ಇತರ ಆ್ಯಪ್‌ಗೆ ಪ್ರವೇಶವನ್ನು ನೀಡಿದ್ದೀರಿ}one{ನೀವು ವಾಹನ ಚಲಾಯಿಸುವಾಗ, <xliff:g id="APP_1">%1$s</xliff:g> ಮತ್ತು # ಇತರ ಆ್ಯಪ್‌ಗಳಿಗೆ ಪ್ರವೇಶವನ್ನು ನೀಡಿದ್ದೀರಿ}other{ನೀವು ವಾಹನ ಚಲಾಯಿಸುವಾಗ, <xliff:g id="APP_1">%1$s</xliff:g> ಮತ್ತು # ಇತರ ಆ್ಯಪ್‌ಗಳಿಗೆ ಪ್ರವೇಶವನ್ನು ನೀಡಿದ್ದೀರಿ}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"ಸೆಟ್ಟಿಂಗ್‌ಗಳಿಗೆ ಹೋಗಿ"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"ಹಲವಾರು ತಿಂಗಳುಗಳಿಂದ ಕೆಲವು ಆ್ಯಪ್‌ಗಳನ್ನು ಬಳಸಲಾಗಿಲ್ಲ"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"ತೆಗೆದುಹಾಕಲಾದ ಅನುಮತಿಗಳು"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"ಅನುಮತಿಗಳನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"ನಿಮ್ಮ ಫೋನ್‌ ಕರೆಯ ಲಾಗ್‌ಗಳಿಗೆ ಪ್ರವೇಶ ಪಡೆಯಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"ಫೋನ್ ಕರೆಗಳನ್ನು ಮಾಡಲು ಮತ್ತು ನಿರ್ವಹಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"ನಿಮ್ಮ ಮುಖ್ಯ ಲಕ್ಷಣಗಳ ಕುರಿತು ಸೆನ್ಸರ್ ಡೇಟಾವನ್ನು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"ನೀವು ಈ ಆ್ಯಪ್ ಅನ್ನು ಬಳಸದಿರುವಾಗಲೂ ಸಹ ಯಾವಾಗಲೂ ನಿಮ್ಮ ಮುಖ್ಯ ಲಕ್ಷಣಗಳ ಕುರಿತ ಸೆನ್ಸರ್ ಡೇಟಾವನ್ನು ಹೊಂದಲು ಆ್ಯಪ್ ಬಯಸುತ್ತದೆ. "<annotation id="link">"ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಅನುಮತಿಸಿ."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"ನೀವು ಆ್ಯಪ್ ಬಳಸದಿರುವಾಗಲೂ ಸಹ, ನಿಮ್ಮ ಆರೋಗ್ಯ ಮಾಪನಗಳ ಕುರಿತು ಎಲ್ಲಾ ಸಮಯದಲ್ಲೂ ಸೆನ್ಸರ್ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಲು ಈ ಆ್ಯಪ್ ಬಯಸುತ್ತದೆ. ಈ ಬದಲಾವಣೆಯನ್ನು ಮಾಡಲು, "<annotation id="link">"ಸೆಟ್ಟಿಂಗ್‌ಗಳಿಗೆ ಹೋಗಿ."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"ನಿಮ್ಮ ಮುಖ್ಯ ಲಕ್ಷಣಗಳ ಕುರಿತ ಸೆನ್ಸರ್ ಡೇಟಾವನ್ನು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"ನೀವು ಈ ಆ್ಯಪ್ ಅನ್ನು ಬಳಸದಿರುವಾಗಲೂ ಸಹ ಯಾವಾಗಲೂ ನಿಮ್ಮ ಮುಖ್ಯ ಲಕ್ಷಣಗಳ ಕುರಿತ ಸೆನ್ಸರ್ ಡೇಟಾವನ್ನು ಹೊಂದಲು ಆ್ಯಪ್ ಬಯಸಬಹುದು. "<annotation id="link">"ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಅನುಮತಿಸಿ."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"ನಿಮ್ಮ ಮುಖ್ಯ ಲಕ್ಷಣಗಳ ಕುರಿತ ಸೆನ್ಸರ್ ಡೇಟಾವನ್ನು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಬದಲಾಯಿಸಬೇಕೇ?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"ನೀವು ಆ್ಯಪ್ ಅನ್ನು ಬಳಸದಿರುವಾಗಲೂ ಸಹ, ಎಲ್ಲಾ ಸಮಯದಲ್ಲೂ ದೇಹದ ಸೆನ್ಸರ್‌ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಲು ಈ ಆ್ಯಪ್ ಅನ್ನು ಅನುಮತಿಸಲು, "<annotation id="link">"ಸೆಟ್ಟಿಂಗ್‌ಗಳಿಗೆ ಹೋಗಿ."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"ಆ್ಯಪ್ ಬಳಕೆಯಲ್ಲಿರುವಾಗ ದೇಹದ ಸೆನ್ಸರ್‌ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸುತ್ತಿರಬೇಕೇ?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"ನಿಮಗೆ ಅಧಿಸೂಚನೆಗಳನ್ನು ಕಳುಹಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"ನಿಮಗೆ ಅಧಿಸೂಚನೆಗಳು ಕಳುಹಿಸುವುದನ್ನು ಮುಂದುವರಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"ನಿಯಂತ್ರಿತ ಅನುಮತಿಗಳು"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"ಕ್ಯಾಮರಾ ಅನುಮತಿಯನ್ನು ತೆಗೆದುಹಾಕಿ"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"ಮೈಕ್ರೊಫೋನ್ ಅನುಮತಿಯನ್ನು ತೆಗೆದುಹಾಕಿ"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"ಸೇವೆಯನ್ನು ನಿರ್ವಹಿಸಿ"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"ಅನುಮತಿಗಳನ್ನು ನಿರ್ವಹಿಸಿ"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"ಫೋನ್ ಕರೆಯು ಇದನ್ನು ಬಳಸುತ್ತಿದೆ"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"ಫೋನ್ ಕರೆಯಲ್ಲಿ ಇತ್ತೀಚಿಗೆ ಬಳಸಲಾಗಿದೆ"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಇದನ್ನು ಬಳಸುತ್ತಿದೆ"</string>
diff --git a/PermissionController/res/values-ko/strings.xml b/PermissionController/res/values-ko/strings.xml
index 70c5abdfe..15623f323 100644
--- a/PermissionController/res/values-ko/strings.xml
+++ b/PermissionController/res/values-ko/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"<xliff:g id="APP">%1$s</xliff:g> 권한 모두 보기"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"이 권한이 있는 앱 모두 보기"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"어시스턴트 마이크 사용 표시"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"사용하지 않는 앱 설정"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"앱이 사용되지 않는 경우 권한 삭제"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"권한을 삭제하고 여유 공간 확보"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"데이터 보호를 위해 몇 개월 동안 앱을 사용하지 않으면 앱의 권한이 삭제됩니다."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"데이터 보호를 위해 몇 개월 동안 앱을 사용하지 않으면 다음 권한이 삭제됩니다. <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"데이터 보호를 위해 몇 개월 동안 사용하지 않은 앱에서 권한이 삭제되었습니다."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"운전 중 <xliff:g id="APP">%1$s</xliff:g>에 <xliff:g id="PERMISSION_1">%2$s</xliff:g> 및 <xliff:g id="PERMISSION_2">%3$s</xliff:g> 액세스 권한을 부여했습니다."</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"운전 중 <xliff:g id="APP">%2$s</xliff:g>에 <xliff:g id="COUNT">%1$d</xliff:g>개의 권한을 부여했습니다."</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{운전 중 <xliff:g id="APP_0">%1$s</xliff:g> 외 #개의 앱에 액세스 권한을 부여했습니다.}other{운전 중 <xliff:g id="APP_1">%1$s</xliff:g> 외 #개의 앱에 액세스 권한을 부여했습니다.}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"설정으로 이동"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"일부 앱을 몇 개월 동안 사용하지 않았습니다."</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"권한이 삭제된 앱"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"권한이 삭제된 앱"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 통화 기록에 액세스하도록 허용하시겠습니까?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 전화를 걸고 관리하도록 허용하시겠습니까?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 생체 신호에 관한 센서 데이터에 액세스하도록 허용하시겠습니까?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"앱을 사용하고 있지 않을 때도 앱에서 생체 신호 센서 데이터에 항상 액세스하려고 합니다. "<annotation id="link">"설정에서 액세스 허용하기"</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"앱이 사용되고 있지 않을 때도 항상 활력 징후 센서 데이터에 액세스하고자 합니다. 권한 변경: "<annotation id="link">"설정으로 이동"</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 생체 신호에 관한 센서 데이터에 액세스하도록 허용하시겠습니까?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"앱을 사용하고 있지 않을 때도 앱에서 항상 센서 데이터에 액세스하고자 할 수 있습니다. "<annotation id="link">"설정에서 액세스 허용하기"</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;의 생체 신호 센서 데이터 액세스를 변경하시겠습니까?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"앱을 사용하지 않을 때도 앱이 항상 생체 신호 센서 데이터에 액세스하도록 허용하려면 "<annotation id="link">"설정으로 이동"</annotation>"하세요"</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; 앱이 사용 중에 생체 신호 센서 데이터에 액세스하는 설정을 유지하시겠습니까?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 알림을 보내도록 허용하시겠습니까?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 계속 알림을 보내도록 허용하시겠습니까?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"관리 대상 권한"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"카메라 권한 삭제"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"마이크 권한 삭제"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"서비스 관리"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"권한 관리"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"전화 통화에서 사용 중"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"최근 전화 통화에서 사용됨"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 사용 중"</string>
diff --git a/PermissionController/res/values-ky/strings.xml b/PermissionController/res/values-ky/strings.xml
index 04bbb37b5..5defc12a6 100644
--- a/PermissionController/res/values-ky/strings.xml
+++ b/PermissionController/res/values-ky/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Бардык <xliff:g id="APP">%1$s</xliff:g> уруксаттарын көрүү"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Ушундай уруксат берилген бардык колдонмолорду көрүү"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Кошумча микрофондун иштешин көрсөтүү"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Иштетилбеген колдонмолордун жөндөөлөрү"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Эгер колдонмо пайдаланылбаса, уруксаттар өчүрүлсүн"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Уруксаттарды өчүрүп, орун бошотуу"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Эгер колдонмо бир нече ай пайдаланылбаса, жеке маалыматтарыңызды коргоо үчүн бул колдонмого берилген уруксаттар өчүрүлөт."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Эгер колдонмо бир нече ай пайдаланылбаса, жеке дайын-даректериңизди коргоо максатында төмөнкү уруксаттар өчүрүлөт: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Жеке дайын-даректериңизди коргоо максатында, бир нече айдан бери ачылбаган колдонмолордогу уруксаттар өчүрүлдү."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Унаа айдап баратканда <xliff:g id="APP">%1$s</xliff:g> колдонмосуна төмөнкүгө уруксат бердиңиз: <xliff:g id="PERMISSION_1">%2$s</xliff:g> жана <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Унаа айдап баратканда <xliff:g id="APP">%2$s</xliff:g> колдонмосуна <xliff:g id="COUNT">%1$d</xliff:g> уруксат бердиңиз"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Унаа айдап баратканда <xliff:g id="APP_0">%1$s</xliff:g> жана дагы # колдонмого уруксат бердиңиз}other{Унаа айдап баратканда <xliff:g id="APP_1">%1$s</xliff:g> жана дагы # колдонмого уруксат бердиңиз}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Жөндөөлөргө өтүү"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Айрым колдонмолор бир нече ай иштетилген жок"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Өчүрүлгөн уруксаттар"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Уруксаттар өчүрүлдү"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна телефондогу чалуулар тизмесин пайдаланууга уруксат бересизби?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна телефон чалууга жана чалууларды башкарууга уруксат бересизби?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна организмдин абалына көз салган сенсордун көрсөткүчтөрүн көрүүгө уруксат бересизби?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Бул колдонмону колдонбой турсаңыз деле, ал такай организмдин негизги көрсөткүчтөрү тууралуу cенсордун дайындарын жаздыра берет. "<annotation id="link">"Ага жөндөөлөрдөн уруксат бериңиз."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Бул колдонмону иштетпей турсаңыз деле, ал такай организмдин негизги көрсөткүчтөрү тууралуу cенсордун дайындарын жаздыра алат. Муну өзгөртүү үчүн "<annotation id="link">"жөндөөлөргө өтүңүз."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна организмдин абалына көз салган сенсордун дайындарын пайдаланууга уруксат берилсинби?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Бул колдонмону колдонбой турсаңыз деле, ал такай организмдин негизги көрсөткүчтөрү тууралуу cенсордун дайындарын жаздыра алат. "<annotation id="link">"Ага жөндөөлөрдөн уруксат бериңиз."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; үчүн организмдин негизги көрсөткүчтөрү тууралуу cенсордун дайындарын алуу мүмкүнчүлүгү өзгөрсүнбү?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Бул колдонмого дене сенсорлорунун дайындарына каалаган убакта кирүү (колдонмону иштетпей жатканда да) мүмкүнчүлүгүн берүү үчүн "<annotation id="link">"жөндөөлөргө өтүңүз."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Колдонулуп жатканда &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; дене сенсорлорунун дайындарына кире берсинби?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна сизге билдирмелерди жөнөтүүгө уруксат бересизби?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосу сизге билдирмелерди жөнөтө берсинби?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Көзөмөлдөнгөн уруксаттар"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Камераны колдонуу уруксатын өчүрүү"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Микрофонду колдонуу уруксатын өчүрүү"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Кызматты башкаруу"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Уруксаттарды башкаруу"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Телефон чалууда иштеп жатат"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Акыркы жолу телефон чалууда колдонулду"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда иштеп жатат"</string>
diff --git a/PermissionController/res/values-lo/strings.xml b/PermissionController/res/values-lo/strings.xml
index ddc51db2a..aaaa925de 100644
--- a/PermissionController/res/values-lo/strings.xml
+++ b/PermissionController/res/values-lo/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"ເບິ່ງສິດອະນຸຍາດ <xliff:g id="APP">%1$s</xliff:g> ທັງໝົດ"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"ເບິ່ງແອັບທັງໝົດທີ່ມີສິດອະນຸຍາດນີ້"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"ສະແດງການໃຊ້ໄມໂຄຣໂຟນຂອງຜູ້ຊ່ວຍ"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"ການຕັ້ງຄ່າແອັບທີ່ບໍ່ໄດ້ໃຊ້"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"ລຶບສິດອະນຸຍາດຫາກບໍ່ໄດ້ໃຊ້ແອັບ"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"ລຶບການອະນຸຍາດອອກ ແລະ ສ້າງພື້ນທີ່ຫວ່າງ"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"ເພື່ອປົກປ້ອງຂໍ້ມູນຂອງທ່ານ, ສິດອະນຸຍາດສຳລັບແອັບນີ້ຈະຖືກລຶບອອກຫາກບໍ່ໄດ້ໃຊ້ແອັບສອງສາມເດືອນ."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"ເພື່ອປົກປ້ອງຂໍ້ມູນຂອງທ່ານ, ຫາກບໍ່ໄດ້ໃຊ້ແອັບສອງສາມເດືອນ, ສິດອະນຸຍາດຕໍ່ໄປນີ້ຈະຖືກລຶບອອກ: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"ເພື່ອປົກປ້ອງຂໍ້ມູນຂອງທ່ານ, ລະບົບໄດ້ລຶບສິດອະນຸຍາດອອກຈາກແອັບຕ່າງໆທີ່ທ່ານບໍ່ໄດ້ໃຊ້ສອງສາມເດືອນແລ້ວ."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"ໃນຂະນະກຳລັງຂັບລົດ, ທ່ານໃຫ້ການເຂົ້າເຖິງ <xliff:g id="PERMISSION_1">%2$s</xliff:g> ແລະ <xliff:g id="PERMISSION_2">%3$s</xliff:g> ໃຫ້ກັບ <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"ໃນຂະນະກຳລັງຂັບລົດ, ທ່ານໃຫ້ການອະນຸຍາດ <xliff:g id="COUNT">%1$d</xliff:g> ລາຍການໃຫ້ກັບ <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{ໃນຂະນະກຳລັງຂັບລົດ, ທ່ານໃຫ້ສິດເຂົ້າເຖິງ <xliff:g id="APP_0">%1$s</xliff:g> ແລະ ແອັບອື່ນໆອີກ # ແອັບ}other{ໃນຂະນະກຳລັງຂັບລົດ, ທ່ານໃຫ້ສິດເຂົ້າເຖິງ <xliff:g id="APP_1">%1$s</xliff:g> ແລະ ແອັບອື່ນໆອີກ # ແອັບ}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"ໄປຫາການຕັ້ງຄ່າ"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"ບາງແອັບບໍ່ໄດ້ໃຊ້ມາສອງສາມເດືອນແລ້ວ"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"ລຶບສິດອະນຸຍາດອອກແລ້ວ"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"ລຶບສິດອະນຸຍາດອອກແລ້ວ"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"ອະນຸຍາດໃຫ້ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ເຂົ້າເຖິງບັນທຶກການໂທທັງໝົດຂອງທ່ານໄດ້ບໍ?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ໂທ ແລະ ຈັດການການໂທບໍ?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ເຂົ້າເຖິງຂໍ້ມູນເຊັນເຊີກ່ຽວກັບສັນຍານຊີບຂອງທ່ານບໍ?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"ແອັບນີ້ຕ້ອງການເຂົ້າເຖິງຂໍ້ມູນເຊັນເຊີກ່ຽວກັບສັນຍານຊີບຂອງທ່ານຕະຫຼອດເວລາ, ເຖິງແມ່ນວ່າທ່ານຈະບໍ່ໄດ້ກຳລັງໃຊ້ແອັບຢູ່ກໍຕາມ. "<annotation id="link">"ອະນຸຍາດໃນການຕັ້ງຄ່າ."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"ແອັບນີ້ຕ້ອງການເຂົ້າເຖິງຂໍ້ມູນເຊັນເຊີກ່ຽວກັບສັນຍານຊີບຂອງທ່ານຕະຫຼອດເວລາ, ເຖິງແມ່ນວ່າທ່ານຈະບໍ່ໄດ້ກຳລັງໃຊ້ແອັບຢູ່ກໍຕາມ. ເພື່ອປ່ຽນແປງສິ່ງນີ້, "<annotation id="link">"ໃຫ້ເຂົ້າໄປການຕັ້ງຄ່າ."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ເຂົ້າເຖິງຂໍ້ມູນເຊັນເຊີກ່ຽວກັບສັນຍານຊີບຂອງທ່ານບໍ?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"ແອັບນີ້ອາດຕ້ອງການເຂົ້າເຖິງຂໍ້ມູນເຊັນເຊີກ່ຽວກັບສັນຍານຊີບຂອງທ່ານຕະຫຼອດເວລາ, ເຖິງແມ່ນວ່າທ່ານຈະບໍ່ໄດ້ກຳລັງໃຊ້ແອັບຢູ່ກໍຕາມ. "<annotation id="link">"ອະນຸຍາດໃນການຕັ້ງຄ່າ."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"ປ່ຽນການເຂົ້າເຖິງຂໍ້ມູນເຊັນເຊີກ່ຽວກັບສັນຍານຊີບຂອງທ່ານສຳລັບ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ບໍ?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"ເພື່ອເຮັດໃຫ້ແອັບນີ້ເຂົ້າເຖິງຂໍ້ມູນເຊັນເຊີຮ່າງກາຍໄດ້ຕະຫຼອດເວລາ, ເຖິງແມ່ນວ່າທ່ານຈະບໍ່ໄດ້ກຳລັງໃຊ້ແອັບຢູ່ກໍຕາມ, "<annotation id="link">"ໃຫ້ເຂົ້າໄປການຕັ້ງຄ່າ."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"ສືບຕໍ່ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ເຂົ້າເຖິງຂໍ້ມູນເຊັນເຊີຮ່າງກາຍໃນຂະນະທີ່ກຳລັງໃຊ້ແອັບຢູ່ບໍ?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"ອະນຸຍາດໃຫ້ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ສົ່ງການແຈ້ງເຕືອນຫາທ່ານບໍ?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"ອະນຸຍາດໃຫ້ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ສືບຕໍ່ສົ່ງການແຈ້ງເຕືອນຫາທ່ານບໍ?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"ສິດອະນຸຍາດທີ່ມີການຄວບຄຸມ"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"ລຶບການອະນຸຍາດກ້ອງຖ່າຍຮູບອອກ"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"ລຶບການອະນຸຍາດໄມໂຄຣໂຟນອອກ"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"ຈັດການບໍລິການ"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"ຈັດການການອະນຸຍາດ"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"ກຳລັງຖືກໃຊ້ໂດຍການໂທລະສັບ"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"ໃຊ້ຫຼ້າສຸດໃນການໂທລະສັບ"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"ກຳລັງຖືກໃຊ້ໂດຍ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-lt/strings.xml b/PermissionController/res/values-lt/strings.xml
index 4ab2eff91..67e7d0bae 100644
--- a/PermissionController/res/values-lt/strings.xml
+++ b/PermissionController/res/values-lt/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Žr. visus „<xliff:g id="APP">%1$s</xliff:g>“ leidimus"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Žr. visas programas, kurioms suteiktas šis leidimas"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Rodyti Padėjėjo mikrofono naudojimą"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Nenaudojamos programos nustatymai"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Pašalinti leidimus, jei programa nenaudojama"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Pašalinti leidimus ir atlaisvinti vietos"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Siekiant apsaugoti duomenis, šios programos leidimai bus pašalinti, jei programos nenaudosite kelis mėnesius."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Siekiant apsaugoti duomenis, jei programos nenaudosite kelis mėnesius, bus pašalinti nurodyti leidimai: <xliff:g id="PERMS">%1$s</xliff:g>."</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Siekiant apsaugoti duomenis, leidimai buvo pašalinti iš programų, kurių nenaudojote kelis mėnesius"</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Vairuodami suteikėte programai „<xliff:g id="APP">%1$s</xliff:g>“ prieigą prie šių leidimų: <xliff:g id="PERMISSION_1">%2$s</xliff:g> ir <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Vairuodami programai „<xliff:g id="APP">%2$s</xliff:g>“ suteikėte tiek leidimų: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Vairuodami suteikėte prieigą programai „<xliff:g id="APP_0">%1$s</xliff:g>“ ir dar # programai}one{Vairuodami suteikėte prieigą programai „<xliff:g id="APP_1">%1$s</xliff:g>“ ir dar # programai}few{Vairuodami suteikėte prieigą programai „<xliff:g id="APP_1">%1$s</xliff:g>“ ir dar # programoms}many{Vairuodami suteikėte prieigą programai „<xliff:g id="APP_1">%1$s</xliff:g>“ ir dar # programos}other{Vairuodami suteikėte prieigą programai „<xliff:g id="APP_1">%1$s</xliff:g>“ ir dar # programų}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Eiti į skiltį „Nustatymai“"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Kai kurios programos nebuvo naudojamos kelis mėnesius"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Pašalinti leidimai"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Pašalinti leidimai"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Leisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pasiekti jūsų telefono skambučių žurnalus?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Leisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; skambinti ir tvarkyti telefono skambučius?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Suteikti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; galimybę pasiekti jutiklių duomenis apie gyvybinius ženklus?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Ši programa nori pasiekti duomenis apie jūsų gyvybinių funkcijų rodiklius visą laiką, net kai programos nenaudojate. "<annotation id="link">"Leiskite skiltyje „Nustatymai“."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Ši programa nori pasiekti jutiklių duomenis apie jūsų gyvybinių funkcijų rodiklius visą laiką, net kai programos nenaudojate. Kad atliktumėte šį pakeitimą, "<annotation id="link">"eikite į skiltį „Nustatymai“."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Suteikti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; galimybę pasiekti jutiklių duomenis apie gyvybinių funkcijų rodiklius?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Programa gali norėti pasiekti jutiklių duomenis apie jūsų gyvybinių funkcijų rodiklius, net kai programos nenaudojate. "<annotation id="link">"Leiskite skiltyje „Nustatymai“."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Pakeisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prieigą prie jutiklių duomenų apie jūsų gyvybinių funkcijų rodiklius?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Jei norite leisti šiai programai pasiekti kūno jutiklių duomenis visą laiką, net kai nenaudojate programos, "<annotation id="link">"eikite į „Nustatymų“ skiltį."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Toliau leisti programai &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pasiekti kūno jutiklių duomenis, kai programa naudojama?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Leisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; siųsti jums pranešimus?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Leisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toliau siųsti jums pranešimus?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Valdomi leidimai"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Pašalinti vaizdo kameros leidimą"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Pašalinti mikrofono leidimą"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Tvarkyti paslaugą"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Tvarkyti leidimus"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Naudojama telefono skambučiui"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Neseniai naudota telefono skambučiui"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Naudojama „<xliff:g id="APP_NAME">%1$s</xliff:g>“"</string>
diff --git a/PermissionController/res/values-lv/strings.xml b/PermissionController/res/values-lv/strings.xml
index a4f663b0f..fb4ce403d 100644
--- a/PermissionController/res/values-lv/strings.xml
+++ b/PermissionController/res/values-lv/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Skatīt visas lietotnei <xliff:g id="APP">%1$s</xliff:g> piešķirtās atļaujas"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Skatīt visas lietotnes, kam ir šī atļauja"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Rādīt Asistenta mikrofona lietojumu"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Neizmantoto lietotņu iestatījumi"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Noņemt atļaujas, ja lietotne netiek izmantota"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Noņemt atļaujas un atbrīvot vietu"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Ja lietotni dažus mēnešus neizmantosiet, tai tiks noņemtas tālāk norādītās atļaujas, lai aizsargātu jūsu datus."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Ja lietotni dažus mēnešus neizmantosiet, tai tiks noņemtas tālāk norādītās atļaujas, lai aizsargātu jūsu datus: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Lai aizsargātu jūsu datus, tika atsauktas atļaujas tām lietotnēm, kas nav izmantotas vairākus mēnešus."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Braukšanas laikā jūs piešķīrāt lietotnei <xliff:g id="APP">%1$s</xliff:g> atļaujas “<xliff:g id="PERMISSION_1">%2$s</xliff:g>” un “<xliff:g id="PERMISSION_2">%3$s</xliff:g>”."</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Braukšanas laikā jūs piešķīrāt atļaujas (<xliff:g id="COUNT">%1$d</xliff:g>) lietotnei <xliff:g id="APP">%2$s</xliff:g>."</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Braukšanas laikā jūs piešķīrāt atļaujas lietotnei <xliff:g id="APP_0">%1$s</xliff:g> un vēl # lietotnei.}zero{Braukšanas laikā jūs piešķīrāt atļaujas lietotnei <xliff:g id="APP_1">%1$s</xliff:g> un vēl # lietotnēm.}one{Braukšanas laikā jūs piešķīrāt atļaujas lietotnei <xliff:g id="APP_1">%1$s</xliff:g> un vēl # lietotnei.}other{Braukšanas laikā jūs piešķīrāt atļaujas lietotnei <xliff:g id="APP_1">%1$s</xliff:g> un vēl # lietotnēm.}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Pāriet uz iestatījumiem"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Dažas lietotnes nav izmantotas vairākus mēnešus."</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Noņemtās atļaujas"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Atļaujas noņemtas"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļūt jūsu tālruņa zvanu žurnāliem?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; veikt un pārvaldīt tālruņa zvanus?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļūt sensoru uztvertajiem veselības rādījumiem?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Lietotne pieprasa atļauju vienmēr piekļūt veselības rādītāju sensoru datiem (arī kad tā netiek lietota). "<annotation id="link">"Atļauju varat piešķirt iestatījumos."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Lietotne pieprasa atļauju piekļūt veselības rādījumu sensoru datiem vienmēr, pat ja neizmantojat lietotni. Lai veiktu šīs izmaiņas, "<annotation id="link">"pārejiet uz iestatījumiem"</annotation>"."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļūt veselības rādītāju sensoru datiem?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Šī lietotne var pieprasīt atļauju vienmēr piekļūt veselības rādītāju sensoru datiem (arī kad tā netiek lietota). "<annotation id="link">"Atļauju varat piešķirt iestatījumos."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Vai mainīt lietotnes &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļuvi veselības rādītāju sensoru datiem?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Lai atļautu šai lietotnei piekļūt ķermeņa sensoru datiem vienmēr (pat tad, kad neizmantojat lietotni), "<annotation id="link">"pārejiet uz iestatījumiem"</annotation>"."</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Vai joprojām atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļūt ķermeņa sensoru datiem, kad izmantojat lietotni?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sūtīt jums paziņojumus?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; turpināt sūtīt jums paziņojumus?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Kontrolētās atļaujas"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Noņemt kameras atļauju"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Noņemt mikrofona atļauju"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Pārvaldīt pakalpojumu"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Pārvaldīt atļaujas"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"To izmanto tālruņa zvans"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Nesen to izmantoja tālruņa zvanā"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"To izmanto lietotne <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-mk/strings.xml b/PermissionController/res/values-mk/strings.xml
index dc6558187..c9e5a6e1d 100644
--- a/PermissionController/res/values-mk/strings.xml
+++ b/PermissionController/res/values-mk/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Прикажи ги сите дозволи за <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Прикажи ги сите апликации со оваа дозвола"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Прикажи го користењето на микрофонот на „Помошникот“"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Поставки за некористени апликации"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Отстрани ги дозволите ако апликацијата не се користи"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Отстранувај дозволи и ослободувај простор"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"За да се заштитат вашите податоци, дозволите за апликацијава ќе се отстранат ако апликацијата не се користи неколку месеци."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Ако апликацијата не се користи неколку месеци, заради заштита на податоците, ќе се отстранат следниве дозволи: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"За заштита на податоците, отстранети се дозволите од апликациите што не сте ги користеле неколку месеци."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Додека возевте, дадовте пристап на <xliff:g id="APP">%1$s</xliff:g> за <xliff:g id="PERMISSION_1">%2$s</xliff:g> и <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Додека возевте, дадовте <xliff:g id="COUNT">%1$d</xliff:g> дозволи на <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Додека возевте, дадовте пристап на <xliff:g id="APP_0">%1$s</xliff:g> и # друга апликација}one{Додека возевте, дадовте пристап на <xliff:g id="APP_1">%1$s</xliff:g> и # друга апликација}other{Додека возевте, дадовте пристап на <xliff:g id="APP_1">%1$s</xliff:g> и # други апликации}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Одете во „Поставки“"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Некои апликации не се користени неколку месеци"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Одземени дозволи"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Отстранети дозволи"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да пристапува до евиденцијата на повици?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да повикува и да управува со телефонските повици?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да пристапува до податоците на сензорот за витални знаци?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Апликцијава сака да пристапува до податоците од сензорите за вашите витални знаци цело време, дури и кога не се користи. "<annotation id="link">"Дозволете во поставките."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Апликцијава сака да пристапува до податоците од сензорите за вашите витални знаци цело време, дури и кога не се користи. За да ја извршите пормената, "<annotation id="link">"одете во „Поставки“."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Дали да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да пристапува до податоците од сензорите за витални знаци?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Апликацијава можеби ќе сака пристап до податоците од сензорите за вашите витални знаци цело време, дури и кога не се користи. "<annotation id="link">"Дозволете во „Поставки“."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Променете го пристапот до податоците од сензорите за вашите витални знаци за &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"За да дозволите апликацијава да пристапува до податоци од телесните сензори цело време, дури и кога не ја користите, "<annotation id="link">"одете во „Поставки“."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"И понатаму да се дозволи пристап на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; до податоци од телесните сензори додека се користи апликацијата?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да ви испраќа известувања?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; и понатаму да ви испраќа известувања?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Контролирани дозволи"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Отстранете ја дозволата за камерата"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Отстранете ја дозволата за микрофонот"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Управувајте со услугата"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Управувајте со дозволите"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Се користи од телефонски повик"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Неодамна користено од телефонски повик"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Се користи од <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-ml/strings.xml b/PermissionController/res/values-ml/strings.xml
index b49348fb1..fc5231feb 100644
--- a/PermissionController/res/values-ml/strings.xml
+++ b/PermissionController/res/values-ml/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"എല്ലാ <xliff:g id="APP">%1$s</xliff:g> അനുമതികളും കാണുക"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"ഈ അനുമതിയുള്ള എല്ലാ ആപ്പുകളും കാണുക"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"സഹായ മൈക്രോഫോൺ ഉപയോഗം കാണിക്കുക"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"ഉപയോഗിക്കാത്ത ആപ്പ് ക്രമീകരണം"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"ഉപയോഗിക്കാത്ത ആപ്പാണെങ്കിൽ അനുമതികൾ നീക്കം ചെയ്യുക"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"അനുമതികൾ നീക്കം ചെയ്‌ത് ഇടം സൃഷ്‌ടിക്കുക"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"മാസങ്ങളായി ഈ ആപ്പ് ഉപയോഗിക്കുന്നില്ലെങ്കിൽ നിങ്ങളുടെ ഡാറ്റ സംരക്ഷിക്കുന്നതിന്, ഈ ആപ്പിനുള്ള അനുമതികൾ നീക്കം ചെയ്യുന്നതായിരിക്കും."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"കുറച്ച് മാസം ആപ്പ് ഉപയോഗിച്ചില്ലെങ്കിൽ, നിങ്ങളുടെ ഡാറ്റ സംരക്ഷിക്കുന്നതിന്, ഇനിപ്പറയുന്ന അനുമതികൾ നീക്കം ചെയ്യുന്നതായിരിക്കും: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"നിങ്ങളുടെ ഡാറ്റ സംരക്ഷിക്കുന്നതിന്, കുറച്ച് മാസങ്ങളായി ഉപയോഗിക്കാത്ത ആപ്പുകളിൽ നിന്ന് അനുമതികൾ നീക്കം ചെയ്തിരിക്കുന്നു."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"ഡ്രൈവ് ചെയ്യുന്നതിനിടെ നിങ്ങൾ <xliff:g id="APP">%1$s</xliff:g> ആപ്പിന് <xliff:g id="PERMISSION_1">%2$s</xliff:g>, <xliff:g id="PERMISSION_2">%3$s</xliff:g> എന്നിവയിലേക്ക് ആക്‌സസ് നൽകി"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"ഡ്രൈവ് ചെയ്യുന്നതിനിടെ നിങ്ങൾ <xliff:g id="APP">%2$s</xliff:g> ആപ്പിന് <xliff:g id="COUNT">%1$d</xliff:g> അനുമതികൾ നൽകി"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{ഡ്രൈവ് ചെയ്യുന്നതിനിടെ നിങ്ങൾ <xliff:g id="APP_0">%1$s</xliff:g> എന്നതിനും മറ്റ് # ആപ്പിനും ആക്‌സസ് നൽകി}other{ഡ്രൈവ് ചെയ്യുന്നതിനിടെ നിങ്ങൾ <xliff:g id="APP_1">%1$s</xliff:g> എന്നതിനും മറ്റ് # ആപ്പുകൾക്കും ആക്‌സസ് നൽകി}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"ക്രമീകരണത്തിലേക്ക് പോകുക"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"കുറച്ച് മാസങ്ങളായി ചില ആപ്പുകൾ ഉപയോഗിച്ചിട്ടില്ല"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"അനുമതികൾ നീക്കം ചെയ്‌തവ"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"അനുമതികൾ നീക്കം ചെയ്‌തവ"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"നിങ്ങളുടെ ഫോൺ കോൾ ലോഗുകൾ ആക്സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"ഫോൺ കോളുകൾ ചെയ്യാനും അവ മാനേജ് ചെയ്യാനും &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"നിങ്ങളുടെ ജീവധാരണ ലക്ഷണങ്ങളെ കുറിച്ചുള്ള സെൻസർ ഡാറ്റ ആക്‌സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"ആപ്പ് ഉപയോഗിക്കാത്തപ്പോഴും, നിങ്ങളുടെ വൈറ്റൽ സൈനുകൾ സംബന്ധിച്ച സെൻസർ ഡാറ്റ എപ്പോഴും ഈ ആപ്പിന് ആക്സ് ചെയ്യേണ്ടി വന്നേക്കാം. "<annotation id="link">"ക്രമീകരണത്തിൽ അനുവദിക്കുക."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"ആപ്പ് ഉപയോഗിക്കാത്തപ്പോൾ പോലും, നിങ്ങളുടെ പ്രധാന ആരോഗ്യ വിവര സൂചനകൾ സംബന്ധിച്ച സെൻസർ ഡാറ്റ ഈ ആപ്പിന് എപ്പോഴും ആക്‌സസ് ചെയ്യേണ്ടി വന്നേക്കാം. ഇത് മാറ്റാൻ, "<annotation id="link">"ക്രമീകരണത്തിലേക്ക് പോകുക"</annotation>"."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"നിങ്ങളുടെ വൈറ്റൽ സൈനുകളെ കുറിച്ചുള്ള സെൻസർ ഡാറ്റ ആക്സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"ആപ്പ് ഉപയോഗിക്കാത്തപ്പോഴും, നിങ്ങളുടെ വൈറ്റൽ സൈനുകൾ സംബന്ധിച്ച സെൻസർ ഡാറ്റ എപ്പോഴും ഈ ആപ്പിന് ആക്സ് ചെയ്യേണ്ടി വന്നേക്കാം. "<annotation id="link">"ക്രമീകരണത്തിൽ അനുവദിക്കുക."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"നിങ്ങളുടെ വൈറ്റൽ സൈനുകളെ കുറിച്ചുള്ള സെൻസർ ഡാറ്റയിലേക്ക് &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനുള്ള ആക്‌സസ് മാറ്റണോ?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"ആപ്പ് ഉപയോഗിക്കാത്ത സമയത്ത് ഉൾപ്പെടെ, എല്ലായ്‌പ്പോഴും ബോഡി സെൻസർ ഡാറ്റ ആക്‌സസ് ചെയ്യാൻ ഈ ആപ്പിനെ അനുവദിക്കുന്നതിന് "<annotation id="link">"ക്രമീകരണത്തിലേക്ക് പോകുക."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"ബോഡി സെൻസർ ഡാറ്റ ആക്‌സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കുന്നത് ആപ്പ് ഉപയോഗിക്കുമ്പോഴും തുടരണോ?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"നിങ്ങൾക്ക് അറിയിപ്പുകൾ അയയ്ക്കാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; എന്നതിനെ അനുവദിക്കണോ?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"നിങ്ങൾക്ക് അറിയിപ്പുകൾ അയക്കുന്നത് തുടരാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; എന്നതിനെ അനുവദിക്കണോ?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"നിയന്ത്രിത അനുമതികൾ"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"ക്യാമറാ അനുമതി നീക്കം ചെയ്യുക"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"മൈക്രോഫോൺ അനുമതി നീക്കം ചെയ്യുക"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"സേവനം മാനേജ് ചെയ്യുക"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"അനുമതികൾ മാനേജ് ചെയ്യുക"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"ഫോൺ കോൾ ഉപയോഗിക്കുന്നു"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"ഫോൺ കോളിൽ അടുത്തിടെ ഉപയോഗിച്ചു"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> ഉപയോഗിക്കുന്നു"</string>
diff --git a/PermissionController/res/values-mn/strings.xml b/PermissionController/res/values-mn/strings.xml
index 82a84c1d6..ec7657bc3 100644
--- a/PermissionController/res/values-mn/strings.xml
+++ b/PermissionController/res/values-mn/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"<xliff:g id="APP">%1$s</xliff:g>-н бүх зөвшөөрлийг харах"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Энэ зөвшөөрөлтэй бүх аппыг харах"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Туслах микрофон ашиглалтыг харуулах"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Хэрэглээгүй аппын тохиргоо"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Аппыг ашигладаггүй бол зөвшөөрлийг нь хасах"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Зөвшөөрлийг хасаж, сул зай гаргах"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Таны өгөгдлийг хамгаалах үүднээс энэ аппыг хэдэн сарын турш ашиглахгүй бол зөвшөөрлийг нь хасах болно."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Таны өгөгдлийг хамгаалах үүднээс аппыг хэдэн сарын турш ашиглахгүй бол дараах зөвшөөрлүүдийг хасах болно: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Таны өгөгдлийг хамгаалах үүднээс таны хэдэн сарын турш ашиглаагүй аппуудын зөвшөөрлийг нь хассан."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Та жолоо барих үедээ <xliff:g id="APP">%1$s</xliff:g>-д <xliff:g id="PERMISSION_1">%2$s</xliff:g> болон <xliff:g id="PERMISSION_2">%3$s</xliff:g>-т хандах эрх өгсөн"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Та жолоо барих үедээ <xliff:g id="COUNT">%1$d</xliff:g> зөвшөөрлийг <xliff:g id="APP">%2$s</xliff:g>-д олгосон"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Та жолоо барих үедээ <xliff:g id="APP_0">%1$s</xliff:g> болон бусад аппуудад хандах эрх өгсөн}other{Та жолоо барих үедээ <xliff:g id="APP_1">%1$s</xliff:g> болон # бусад аппад хандах эрх өгсөн}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Тохиргоо руу очих"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Зарим аппыг хэдэн сарын турш ашиглаагүй байна"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Зөвшөөрлүүдийг хассан"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Зөвшөөрлийг хассан"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д таны утасны дуудлагын жагсаалтад хандахыг зөвшөөрөх үү?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д утасны дуудлага хийх, дуудлага удирдахыг зөвшөөрөх үү?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д таны биеийн ерөнхий байдлын үзүүлэлтүүдийн мэдрэгчийн өгөгдөлд хандахыг зөвшөөрөх үү?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Аппыг ашиглаагүй үед ч энэ нь таны биеийн ерөнхий байдлын үзүүлэлтүүдийн талаарх мэдрэгчийн өгөгдөлд үргэлж хандахыг хүсэж байна. "<annotation id="link">"Тохиргоонд зөвшөөр."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Аппыг ашиглаагүй үед ч энэ нь таны биеийн ерөнхий байдлын үзүүлэлтүүдийн талаарх мэдрэгчийн өгөгдөлд үргэлж хандахыг хүсэж байна. Энэ өөрчлөлтийг хийхийн тулд "<annotation id="link">"тохиргоо руу очно уу."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д таны биеийн ерөнхий байдлын үзүүлэлтүүдийн талаарх мэдрэгчийн өгөгдөлд хандахыг зөвшөөрөх үү?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Аппыг ашиглаагүй үед ч энэ нь таны биеийн ерөнхий байдлын үзүүлэлтүүдийн талаарх мэдрэгчийн өгөгдөлд үргэлж хандахыг хүсэж магадгүй "<annotation id="link">"Тохиргоонд зөвшөөр"</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-н таны биеийн ерөнхий байдлын үзүүлэлтүүдийн талаарх мэдрэгчийн өгөгдлийн хандалтыг өөрчлөх үү?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Та аппыг ашиглаагүй байсан ч ямар ч үед энэ аппын биеийн мэрэгчийн өгөгдөлд хандахыг зөвшөөрөх бол "<annotation id="link">"тохиргоо руу очно уу."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Аппыг ашиглаж байх үедээ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-г биеийн мэдрэгчийн өгөгдөлд хандахыг үргэлжлүүлэн зөвшөөрөх үү?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-&lt;/b&gt;-д танд мэдэгдэл илгээхийг зөвшөөрөх үү?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д танд үргэлжлүүлэн мэдэгдэл илгээхийг зөвшөөрөх үү?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Хяналттай зөвшөөрөл"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Камерын зөвшөөрлийг хасах"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Микрофоны зөвшөөрлийг хасах"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Үйлчилгээг удирдах"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Зөвшөөрлийг удирдах"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Утасны дуудлага ашиглаж байна"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Саяхан утасны дуудлагад ашигласан"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> ашиглаж байна"</string>
diff --git a/PermissionController/res/values-mr/strings.xml b/PermissionController/res/values-mr/strings.xml
index 11a04416c..452a7e33a 100644
--- a/PermissionController/res/values-mr/strings.xml
+++ b/PermissionController/res/values-mr/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"सर्व <xliff:g id="APP">%1$s</xliff:g> परवानग्या पहा"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"ही परवानगी असलेली सर्व अ‍ॅप्स पहा"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Assistant ने मायक्रोफोनचा केलेला वापर दाखवा"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"न वापरलेली ॲप सेटिंग्ज"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"अ‍ॅप वापरले नसल्यास, परवानग्या काढून टाका"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"परवानग्या काढा आणि जागा मोकळी करा"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"तुमच्या डेटाचे संरक्षण करण्यासाठी, अ‍ॅप काही महिन्यांत वापरले गेले नसल्यास, या अ‍ॅपच्या परवानग्या काढल्या जातील."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"तुमच्या डेटाचे संरक्षण करण्यासाठी, अ‍ॅप काही महिन्यांत वापरले गेले नसल्यास, पुढील परवानग्या काढल्या जातील: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"तुमच्या डेटाचे संरक्षण करण्यासाठी, तुम्ही काही महिन्यांत न वापरलेल्या ॲप्समधून परवानग्या काढल्या गेल्या आहेत."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"ड्राइव्ह करताना, तुम्ही <xliff:g id="APP">%1$s</xliff:g> ला <xliff:g id="PERMISSION_1">%2$s</xliff:g> &amp; <xliff:g id="PERMISSION_2">%3$s</xliff:g> चा अ‍ॅक्सेस दिला आहे"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"ड्राइव्ह करताना, तुम्ही <xliff:g id="APP">%2$s</xliff:g> ला <xliff:g id="COUNT">%1$d</xliff:g> परवानग्या दिल्या आहेत"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{ड्राइव्ह करताना, तुम्ही <xliff:g id="APP_0">%1$s</xliff:g> &amp; आणखी # ॲपला अ‍ॅक्सेस दिला आहे}other{ड्राइव्ह करताना, तुम्ही <xliff:g id="APP_1">%1$s</xliff:g> &amp; आणि आणखी # ॲप्सना अ‍ॅक्सेस दिला आहे}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"सेटिंग्ज वर जा"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"काही ॲप्‍स काही महिन्यांत वापरलेली नाहीत"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"काढून टाकलेल्या परवानग्या"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"परवानग्या काढून टाकल्या आहेत"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला तुमचे फोन कॉल लॉग अ‍ॅक्सेस करण्याची अनुमती द्यायची का?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला फोन कॉल करू आणि ते व्यवस्थापित करू द्यायचे?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला तुमच्या महत्त्वाच्या लक्षणांविषयीचा सेन्सर डेटा अ‍ॅक्सेस करू द्यायचे?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"तुम्ही अ‍ॅप वापरत नसतानादेखील या ॲपला नेहमी तुमच्या महत्त्वाच्या परिमाणांबद्दलचा सेन्सर डेटा ॲक्सेस करायचा आहे. "<annotation id="link">"सेटिंग्जमध्ये अनुमती द्या."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"तुम्ही अ‍ॅप वापरत नसतानादेखील या ॲपला तुमच्या महत्त्वाच्या परिमाणांबद्दलचा सेन्सर डेटा पूर्णवेळ ॲक्सेस करायचा आहे. हा बदल करण्यासाठी, "<annotation id="link">" सेटिंग्जवर जा."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला तुमच्या महत्त्वाच्या परिमाणांसंबंधित सेन्सर डेटा अ‍ॅक्सेस करण्याची अनुमती द्यायची आहे का?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"तुम्ही ॲप वापरत नसतानाही, या ॲपला तुमच्या महत्त्वाच्या परिमाणांबद्दलचा सेन्सर डेटा कदाचित नेहमी अ‍ॅक्सेस करायचा असू शकतो. "<annotation id="link">"सेटिंग्जमध्ये अनुमती द्या."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"तुमच्या &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; संबंधित महत्त्वाच्या परिमाणांबद्दलच्या सेन्सर डेटाचा अ‍ॅक्सेस बदला?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"तुम्ही ॲप वापरत नसतानादेखील या ॲपला शरीर सेन्सर डेटा नेहमी अ‍ॅक्सेस करू देण्यासाठी, "<annotation id="link">"सेटिंग्जवर जा."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"ॲप वापरात असताना &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला शरीर सेन्सर डेटा अ‍ॅक्सेस करण्याची अनुमती देणे सुरू ठेवायचे आहे का?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला तुम्हाला सूचना पाठवू द्यायचे का?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला तुम्हाला सूचना पाठवणे सुरू ठेवू द्यायचे का?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"नियंत्रित परवानग्या"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"कॅमेरा परवानगी काढून टाका"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"मायक्रोफोन परवानगी काढून टाका"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"सेवा व्यवस्थापित करा"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"परवानग्या व्यवस्थापित करा"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"फोन कॉलद्वारे वापरले जात आहे"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"अलीकडे फोन कॉलमध्ये वापरले गेले"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> द्वारे वापरले जात आहे"</string>
diff --git a/PermissionController/res/values-ms/strings.xml b/PermissionController/res/values-ms/strings.xml
index bc085ba94..542b9cd02 100644
--- a/PermissionController/res/values-ms/strings.xml
+++ b/PermissionController/res/values-ms/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Lihat semua kebenaran <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Lihat semua apl dengan kebenaran ini"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Tunjukkan penggunaan mikrofon pembantu"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Tetapan apl yang tidak digunakan"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Alih keluar kebenaran jika apl tidak digunakan"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Alih keluar kebenaran dan kosongkan ruang"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Untuk melindungi data anda, kebenaran apl ini akan dialih keluar jika apl tidak digunakan selama beberapa bulan."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Untuk melindungi data anda, jika apl tidak digunakan selama beberapa bulan, kebenaran berikut akan dialih keluar: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Untuk melindungi data anda, kebenaran telah dialih keluar daripada apl yang tidak anda gunakan selama beberapa bulan."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Semasa memandu, anda memberi <xliff:g id="APP">%1$s</xliff:g> akses kepada <xliff:g id="PERMISSION_1">%2$s</xliff:g> &amp; <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Semasa memandu, anda memberikan <xliff:g id="COUNT">%1$d</xliff:g> kebenaran kepada <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Semasa memandu, anda memberikan akses kepada <xliff:g id="APP_0">%1$s</xliff:g> &amp; # apl lain}other{Semasa memandu, anda memberikan akses kepada <xliff:g id="APP_1">%1$s</xliff:g> &amp; # apl lain}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Pergi ke Tetapan"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Sesetengah apl tidak digunakan selama beberapa bulan"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Kebenaran dialih keluar"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Kebenaran dialih keluar"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses log panggilan telefon anda?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; membuat dan mengurus panggilan telefon?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses data penderia tentang tanda vital anda?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Apl ini mahu mengakses data penderia tentang tanda vital anda pada setiap masa, meskipun apabila anda tidak menggunakan apl. "<annotation id="link">"Benarkan dalam tetapan."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Apl ini mahu mengakses data penderia tentang tanda vital anda pada setiap masa, meskipun apabila anda tidak menggunakan apl. Untuk membuat perubahan ini, "<annotation id="link">"pergi ke tetapan."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses data penderia tentang tanda vital anda?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Apl ini mungkin mahu mengakses data penderia tentang tanda vital anda pada setiap masa, meskipun apabila anda tidak menggunakan apl. "<annotation id="link">"Benarkan dalam tetapan."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Tukar akses kepada data penderia tentang tanda vital anda untuk &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Untuk membenarkan apl ini mengakses data penderia tubuh pada setiap masa, meskipun apabila anda tidak menggunakan apl, "<annotation id="link">"pergi ke tetapan."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Terus membenarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses data penderia tubuh semasa apl digunakan?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; menghantar pemberitahuan kepada anda?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; terus menghantar pemberitahuan kepada anda?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Kebenaran terkawal"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Alih keluar kebenaran kamera"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Alih keluar kebenaran mikrofon"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Urus perkhidmatan"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Urus kebenaran"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Sedang digunakan oleh panggilan telefon"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Digunakan baru-baru ini dalam panggilan telefon"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Sedang digunakan oleh <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-my/strings.xml b/PermissionController/res/values-my/strings.xml
index 78bab3ab5..dd57438b4 100644
--- a/PermissionController/res/values-my/strings.xml
+++ b/PermissionController/res/values-my/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"<xliff:g id="APP">%1$s</xliff:g> ခွင့်ပြုချက်အားလုံး ကြည့်ရန်"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"ဤခွင့်ပြုချက်ရှိသော အက်ပ်အားလုံးကို ကြည့်ရန်"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Assistant မိုက်ကရိုဖုန်း အသုံးပြုမှုကို ပြပါ"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"အသုံးမပြုသော အက်ပ်ဆက်တင်များ"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"အက်ပ်ကိုအသုံးမပြုလျှင် ခွင့်ပြုချက်များ ဖယ်ရှားရန်"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"ခွင့်ပြုချက်များဖယ်ရှားပြီး နေရာလွတ်ပြုလုပ်ရန်"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"အက်ပ်ကို လအနည်းငယ် အသုံးမပြုပါက သင်၏ဒေတာကိုကာကွယ်ရန် ဤအက်ပ်အတွက် ခွင့်ပြုချက်များကို ဖယ်ရှားပါမည်။"</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"အက်ပ်ကို လအနည်းငယ် အသုံးမပြုပါက သင်၏ဒေတာကိုကာကွယ်ရန် အောက်ပါခွင့်ပြုချက်များကို ဖယ်ရှားပါမည်- <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"သင်၏ဒေတာကိုကာကွယ်ရန် လအနည်းငယ်အတွင်း အသုံးမပြုသော အက်ပ်များမှ ခွင့်ပြုချက်များကို ဖယ်ရှားလိုက်သည်။"</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"မောင်းနှင်နေစဉ် <xliff:g id="APP">%1$s</xliff:g> ကို <xliff:g id="PERMISSION_1">%2$s</xliff:g> နှင့် <xliff:g id="PERMISSION_2">%3$s</xliff:g> သုံးခွင့်ပေးထားသည်"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"မောင်းနှင်နေစဉ် <xliff:g id="APP">%2$s</xliff:g> ကို ခွင့်ပြုချက် <xliff:g id="COUNT">%1$d</xliff:g> ခု ပေးထားသည်"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{မောင်းနှင်နေစဉ် <xliff:g id="APP_0">%1$s</xliff:g> နှင့် အခြားအက်ပ် # ခုကို သုံးခွင့်ပေးထားသည်}other{မောင်းနှင်နေစဉ် <xliff:g id="APP_1">%1$s</xliff:g> နှင့် အခြားအက်ပ် # ခုကို သုံးခွင့်ပေးထားသည်}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"ဆက်တင်များသို့သွားရန်"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"အက်ပ်အချို့ကို အသုံးမပြုသည်မှာ လအနည်းငယ် ရှိပါပြီ"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"ခွင့်ပြုချက် ဖယ်ထားသည်များ"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"ခွင့်ပြုချက် ဖယ်ထားသည်များ"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား သင်၏ခေါ်ဆိုထားသော မှတ်တမ်းများကို သုံးခွင့်ပေးလိုပါသလား။"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ကို ဖုန်းခေါ်ဆိုမှုများ ပြုလုပ်ခွင့်နှင့် စီမံခွင့်ပေးလိုပါသလား။"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား သင်၏ အရေးကြီးသော ကျန်းမာရေးလက္ခဏာဆိုင်ရာ အာရုံခံကိရိယာဒေတာ သုံးခွင့်ပေးလိုပါသလား။"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"ဤအက်ပ်သည် သင်၏ အရေးကြီးသောလက္ခဏာ အာရုံခံစနစ်ဒေတာကို အက်ပ်အသုံးမပြုနေလျှင်ပင် အချိန်ပြည့်သုံးခွင့် ရယူလိုပါသည်။ "<annotation id="link">"ဆက်တင်များတွင် ခွင့်ပြုနိုင်သည်။"</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"အက်ပ်သုံးမနေသော်လည်း ဤအက်ပ်က သင်၏အဓိကကိုယ်တွင်းအင်္ဂါအခြေအနေ လက္ခဏာများနှင့်ပတ်သက်သော အာရုံခံစနစ် ဒေတာကို အမြဲသုံးခွင့် ရယူလိုသည်။ ဤအပြောင်းအလဲကို ပြုလုပ်ရန် "<annotation id="link">"ဆက်တင်များသို့ သွားပါ။"</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား သင်၏ အရေးကြီးသောလက္ခဏာ အာရုံခံစနစ် ဒေတာကို သုံးခွင့်ပေးလိုပါသလား။"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"ဤအက်ပ်သည် သင်၏ အရေးကြီးသောလက္ခဏာ အာရုံခံစနစ်ဒေတာကို အက်ပ်အသုံးမပြုနေလျှင်ပင် အချိန်ပြည့်သုံးခွင့် ရယူလိုပါသည်။ "<annotation id="link">"ဆက်တင်များတွင် ခွင့်ပြုနိုင်သည်။"</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အတွက် အရေးကြီးသောလက္ခဏာ အာရုံခံစနစ် ဒေတာသုံးခွင့်ကို ပြောင်းလိုပါသလား။"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"အက်ပ်သုံးမနေသော်လည်း ဤအက်ပ်ကို ခန္ဓာကိုယ်အာရုံခံစနစ် ဒေတာများ အမြဲသုံးခွင့်ပြုရန် "<annotation id="link">"ဆက်တင်များသို့ သွားပါ။"</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"အက်ပ်သုံးစဉ် &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ကို ခန္ဓာကိုယ်အာရုံခံစနစ် ဒေတာ ဆက်သုံးခွင့်ပြုမလား။"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ကို သင့်ထံ အကြောင်းကြားချက်များ ပို့ခွင့်ပြုမလား။"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ကို သင့်ထံ အကြောင်းကြားချက်များ ဆက်ပို့ခွင့်ပြုမလား။"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"ထိန်းချုပ်ထားသော ခွင့်ပြုချက်များ"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"ကင်မရာခွင့်ပြုချက် ဖယ်ရှားရန်"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"မိုက်ခရိုဖုန်းခွင့်ပြုချက် ဖယ်ရှားရန်"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"ဝန်ဆောင်မှု စီမံခန့်ခွဲရန်"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"ခွင့်ပြုချက်များကို စီမံရန်"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"ဖုန်းခေါ်ဆိုမှုက အသုံးပြုနေသည်"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"ဖုန်းခေါ်ဆိုမှုတွင် မကြာသေးမီက အသုံးပြုထားသည်"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> က အသုံးပြုနေသည်"</string>
diff --git a/PermissionController/res/values-nb/strings.xml b/PermissionController/res/values-nb/strings.xml
index cdbf61583..c6ca5cd54 100644
--- a/PermissionController/res/values-nb/strings.xml
+++ b/PermissionController/res/values-nb/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Se alle tillatelsene <xliff:g id="APP">%1$s</xliff:g> har"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Se alle apper med denne tillatelsen"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Vis bruk av assistentmikrofonen"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Innstillinger for ubrukte apper"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Fjern tillatelser hvis appen ikke brukes"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Fjern tillatelser og frigjør plass"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"For å beskytte dataene dine fjernes tillatelser for denne appen hvis appen ikke brukes på noen måneder."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Hvis appen ikke brukes på noen måneder, fjernes disse tillatelsene for å beskytte dataene dine: <xliff:g id="PERMS">%1$s</xliff:g>."</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"For å beskytte dataene dine har tillatelser blitt fjernet fra apper du ikke har brukt på noen måneder."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Du ga <xliff:g id="APP">%1$s</xliff:g> tilgang til <xliff:g id="PERMISSION_1">%2$s</xliff:g> og <xliff:g id="PERMISSION_2">%3$s</xliff:g> mens du kjørte"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Du ga <xliff:g id="APP">%2$s</xliff:g> <xliff:g id="COUNT">%1$d</xliff:g> tillatelser mens du kjørte"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Du ga <xliff:g id="APP_0">%1$s</xliff:g> og # annen app tilgang mens du kjørte}other{Du ga <xliff:g id="APP_1">%1$s</xliff:g> og # andre aper tilgang mens du kjørte}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Gå til Innstillinger"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Enkelte apper er ikke brukt på noen måneder"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Fjernede tillatelser"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Tillatelser er fjernet"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Vil du gi &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilgang til samtaleloggene dine?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Vil du la &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ringe og administrere telefonsamtaler?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Vil du gi &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilgang til sensordata om de vitale tegnene dine?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Denne appen vil ha tilgang til sensordata om de vitale tegnene dine hele tiden, selv når du ikke bruker appen. "<annotation id="link">"Gi tillatelse i innstillingene."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Denne appen vil ha tilgang til sensordata om de vitale tegnene dine hele tiden, selv når du ikke bruker den. For å gjøre denne endringen, "<annotation id="link">"gå til innstillingene."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Vil du gi &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilgang til sensordataene om de vitale tegnene dine?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Denne appen vil kanskje ha tilgang til sensordataene om de vitale tegnene dine, selv når du ikke bruker appen. "<annotation id="link">"Gi tillatelse i innstillingene."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Vil du endre tilgangen til sensordata om de vitale tegnene dine for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"For å gi denne appen tilgang til data fra kroppssensorer til enhver tid, selv når du ikke bruker den, "<annotation id="link">"gå til innstillingene."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Vil du fortsette å gi &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilgang til data fra kroppssensorer mens appen er i bruk?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Vil du la &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sende deg varsler?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Vil du la &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; fortsette å sende deg varsler?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Kontrollerte tillatelser"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Fjern kameratillatelse"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Fjern mikrofontillatelse"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Administrer tjeneste"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Administrer tillatelser"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Blir brukt av telefonanrop"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Nylig brukt i telefonanrop"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Blir brukt av <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-ne/strings.xml b/PermissionController/res/values-ne/strings.xml
index 8431c7708..4eca1dc30 100644
--- a/PermissionController/res/values-ne/strings.xml
+++ b/PermissionController/res/values-ne/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"<xliff:g id="APP">%1$s</xliff:g>सँग भएका सबै अनुमति हेर्नुहोस्"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"यो अनुमति पाएका सबै एपहरू हेर्नुहोस्"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"सहायकको माइक्रोफोन प्रयोगसम्बन्धी डेटा देखाउनुहोस्"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"प्रयोग नगरिएको एपसम्बन्धी सेटिङ"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"यो एप प्रयोग नहुँदा यसलाई दिइएका अनुमतिहरू रद्द गरियोस्"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"अनुमतिहरू हटाई ठाउँ खाली गरियोस्"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"तपाईंका डेटाको सुरक्षार्थ यो एप केही महिनासम्म प्रयोग नगरिएका खण्डमा यसलाई दिइएका अनुमति रद्द गरिने छन्।"</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"तपाईंका डेटाको सुरक्षार्थ यो एप केही महिनासम्म प्रयोग नगरिएका खण्डमा निम्न अनुमति रद्द गरिने छन्: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"तपाईंका डेटाको सुरक्षार्थ तपाईंले केही महिनादेखि प्रयोग नगरेका एपलाई दिइएका अनुमति रद्द गरिएका छन्।"</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"सवारी साधन चलाइरहेको बेला तपाईंले <xliff:g id="APP">%1$s</xliff:g> लाई <xliff:g id="PERMISSION_1">%2$s</xliff:g> र <xliff:g id="PERMISSION_2">%3$s</xliff:g> प्रयोग गर्ने अनुमति दिनुभयो"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"सवारी साधन चलाइरहेको बेला तपाईंले <xliff:g id="COUNT">%1$d</xliff:g> लाई <xliff:g id="APP">%2$s</xliff:g> प्रयोग गर्ने अनुमति दिनुभयो"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{सवारी साधन चलाइरहेको बेला तपाईंले <xliff:g id="APP_0">%1$s</xliff:g> र अन्य # एप प्रयोग गर्ने अनुमति दिनुभयो}other{सवारी साधन चलाइरहेको बेला तपाईंले <xliff:g id="APP_1">%1$s</xliff:g> र अन्य # एप प्रयोग गर्ने अनुमति दिनुभयो}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"सेटिङमा जानुहोस्"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"तपाईंले केही महिनादेखि केही एपहरू प्रयोग गर्नुभएका छैन"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"अनुमति रद्द गरिएका एपहरू"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"अनुमति रद्द गरिएका एपहरू"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई आफ्ना कल लग प्रयोग गर्ने अनुमति दिने हो?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई फोन कल गर्न र ती कलको व्यवस्थापन गर्न दिने हो?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई आफ्ना महत्त्वपूर्ण लक्षणहरूसम्बन्धी सेन्सर डेटामाथि पहुँच राख्न दिने हो?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"यो एपले जुनसुकै बेला (तपाईंले यसको प्रयोग नगरेका अवस्थामा पनि) स्वास्थ्यसम्बन्धी आधारभूत विवरण उपलब्ध गराउने सेन्सर डेटामाथि पहुँच राख्न सक्छ। "<annotation id="link">"सेटिङमा गई यसो गर्ने अनुमति दिनुहोस्।"</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"यो एप जुनसुकै बेला (तपाईंले एप प्रयोग नगरेका बेलासमेत) तपाईंका शरीरका महत्त्वपूर्ण सङ्केतहरू सेन्सर गर्नेसम्बन्धी डेटा हेर्न र प्रयोग गर्न चाहन्छ। यस्तो परिवर्तन गर्न "<annotation id="link">"सेटिङमा जानुहोस्।"</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई तपाईंको स्वास्थ्यसम्बन्धी आधारभूत विवरण उपलब्ध गराउने सेन्सर डेटामाथि पहुँच राख्ने अनुमति दिने हो?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"यो एपले जुनसुकै बेला (तपाईंले यसको प्रयोग नगरेका अवस्थामा पनि) स्वास्थ्यसम्बन्धी आधारभूत विवरण उपलब्ध गराउने सेन्सर डेटामाथि पहुँच राख्न सक्छ। "<annotation id="link">"सेटिङमा गई यसो गर्ने अनुमति दिनुहोस्।"</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"तपाईंको स्वास्थ्यसम्बन्धी आधारभूत विवरण उपलब्ध गराउने सेन्सर डेटामाथि पहुँच राख्न &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई दिइएको अनुमति बदल्ने हो?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"यो एपलाई जुनसुकै बेला (तपाईंले एप नचलाएका बेलासमेत) बडी सेन्सरसम्बन्धी डेटा हेर्न र प्रयोग गर्न दिन "<annotation id="link">"सेटिङमा जानुहोस्।"</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"यो एप प्रयोग गरिँदै गरेका बेला यसलाई &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; बडी सेन्सरसम्बन्धी डेटा हेर्ने र प्रयोग गर्ने अनुमति दिइरहने हो?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई तपाईंलाई सूचना पठाउन दिने हो?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई तपाईंलाई सूचना पठाइराख्न दिने हो?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"नियन्त्रित अनुमतिहरू"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"क्यामेरा प्रयोग गर्न दिइएको अनुमति हटाउनुहोस्"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"माइक्रोफोन प्रयोग गर्न दिइएको अनुमति हटाउनुहोस्"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"सेवा व्यवस्थित गर्नुहोस्"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"अनुमति व्यवस्थापन गर्नुहोस्"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"फोन कलले प्रयोग गरिरहेको छ"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"फोन कलमा हालसालै प्रयोग गरिएको"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> ले प्रयोग गरिरहेको छ"</string>
diff --git a/PermissionController/res/values-nl/strings.xml b/PermissionController/res/values-nl/strings.xml
index 91efab967..2d80b0711 100644
--- a/PermissionController/res/values-nl/strings.xml
+++ b/PermissionController/res/values-nl/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Alle rechten van <xliff:g id="APP">%1$s</xliff:g> bekijken"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Alle apps met dit recht bekijken"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Gebruik van Assistent-microfoon tonen"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Niet-gebruikte app-instellingen"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Rechten intrekken als app niet wordt gebruikt"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Rechten intrekken en ruimte vrijmaken"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Om je gegevens te beschermen worden de rechten voor deze app verwijderd als de app een aantal maanden niet is gebruikt."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Om je gegevens te beschermen worden de volgende rechten ingetrokken als de app een paar maanden niet is gebruikt: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Om je gegevens te beschermen zijn de rechten verwijderd van apps die al een paar maanden niet zijn gebruikt."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Tijdens het rijden heb je <xliff:g id="APP">%1$s</xliff:g> toegang gegeven tot <xliff:g id="PERMISSION_1">%2$s</xliff:g> en <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Tijdens het rijden heb je <xliff:g id="COUNT">%1$d</xliff:g> rechten gegeven aan <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Tijdens het rijden heb je <xliff:g id="APP_0">%1$s</xliff:g> en # andere app toegang gegeven}other{Tijdens het rijden heb je <xliff:g id="APP_1">%1$s</xliff:g> en # andere apps toegang gegeven}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Naar Instellingen"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Bepaalde apps zijn al een paar maanden niet gebruikt"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Verwijderde rechten"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Rechten verwijderd"</string>
@@ -333,7 +337,7 @@
<string name="role_assistant_request_description" msgid="6836644847620178483">"Krijgt toegang tot sms en gesprekslijst"</string>
<string name="role_browser_label" msgid="2877796144554070207">"Standaard browser-app"</string>
<string name="role_browser_short_label" msgid="6745009127123292296">"Browser-app"</string>
- <string name="role_browser_description" msgid="3465253637499842671">"Apps die toegang tot internet geven en de links weergeven waarop je hebt getikt"</string>
+ <string name="role_browser_description" msgid="3465253637499842671">"Apps die toegang tot internet geven en de links bekijken waarop je hebt getikt"</string>
<string name="role_browser_request_title" msgid="2895200507835937192">"Wil je <xliff:g id="APP_NAME">%1$s</xliff:g> instellen als je standaard browser-app?"</string>
<string name="role_browser_request_description" msgid="5888803407905985941">"Geen rechten nodig"</string>
<string name="role_dialer_label" msgid="1100224146343237968">"Standaard telefoon-app"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang geven tot je gesprekslijsten?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toestaan om telefoongesprekken te starten en te beheren?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang geven tot sensorgegevens over je vitale functies?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Deze app wil altijd toegang tot sensorgegevens over je vitale functies, ook als je de app niet gebruikt. "<annotation id="link">"Toestaan in Instellingen."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Deze app wil altijd toegang tot gegevens van lichaamssensoren met betrekking tot je vitale functies, ook als je de app niet gebruikt. "<annotation id="link">"Ga naar Instellingen"</annotation>" als je deze wijziging wilt doorvoeren."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang geven tot sensorgegevens over je vitale functies?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Deze app wil mogelijk altijd toegang tot sensorgegevens over je vitale functies, ook als je de app niet gebruikt. "<annotation id="link">"Toestaan in Instellingen."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Toegang tot sensorgegevens over je vitale functies wijzigen voor &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783"><annotation id="link">"Ga naar Instellingen"</annotation>" als je deze app altijd toegang tot gegevens van lichaamssensoren wilt geven, ook als je de app niet gebruikt"</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Blijven toestaan dat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot gegevens van lichaamssensoren heeft als de app wordt gebruikt?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Toestaan dat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; jou meldingen stuurt?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Wil je toestaan dat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; je meldingen blijft sturen?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Beheerde rechten"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Camerarecht verwijderen"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Microfoonrecht verwijderen"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Service beheren"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Rechten beheren"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Wordt gebruikt door telefoongesprek"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Recent gebruikt in telefoongesprek"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Wordt gebruikt door <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-or/strings.xml b/PermissionController/res/values-or/strings.xml
index 1d320d22e..a384c49dc 100644
--- a/PermissionController/res/values-or/strings.xml
+++ b/PermissionController/res/values-or/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"ସମସ୍ତ <xliff:g id="APP">%1$s</xliff:g> ଅନୁମତି ଦେଖନ୍ତୁ"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"ଏହି ଅନୁମତି ଥିବା ସମସ୍ତ ଆପ୍ସ ଦେଖନ୍ତୁ"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Assistant ମାଇକ୍ରୋଫୋନ୍ ବ୍ୟବହାର ଦେଖାନ୍ତୁ"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"ଅବ୍ୟବହୃତ ଆପ ସେଟିଂସ"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"ଯଦି ଆପ୍ ବ୍ୟବହାର କରାଯାଇନାହିଁ, ତେବେ ଅନୁମତିଗୁଡ଼ିକୁ କାଢ଼ି ଦିଅନ୍ତୁ"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"ଅନୁମତିଗୁଡ଼ିକୁ କାଢ଼ି ସ୍ପେସ୍ ଖାଲି କରନ୍ତୁ"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"ଯଦି ଏହି ଆପକୁ କିଛି ମାସ ପାଇଁ ବ୍ୟବହାର କରାଯାଇନାହିଁ, ତେବେ ଆପଣଙ୍କ ଡାଟାର ସୁରକ୍ଷା ନିମନ୍ତେ ଏହାର ଅନୁମତିଗୁଡ଼ିକୁ କାଢ଼ି ଦିଆଯିବ।"</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"ଯଦି ଏହି ଆପକୁ କିଛି ମାସ ପାଇଁ ବ୍ୟବହାର କରାଯାଇନାହିଁ ତେବେ ଆପଣଙ୍କ ଡାଟାର ସୁରକ୍ଷା ନିମନ୍ତେ, ନିମ୍ନୋକ୍ତ ଅନୁମତିଗୁଡ଼ିକୁ କାଢ଼ି ଦିଆଯିବ: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"ଆପଣଙ୍କ ଡାଟାର ସୁରକ୍ଷା ପାଇଁ, ଆପଣ କିଛି ମାସ ହେଲା ବ୍ୟବହାର କରିନଥିବା ଆପଗୁଡ଼ିକରୁ ଅନୁମତିଗୁଡ଼ିକୁ କାଢ଼ି ଦିଆଯାଇଛି।"</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"ଡ୍ରାଇଭ କରିବା ସମୟରେ ଆପଣ <xliff:g id="APP">%1$s</xliff:g>କୁ <xliff:g id="PERMISSION_1">%2$s</xliff:g> ଓ <xliff:g id="PERMISSION_2">%3$s</xliff:g> ଆକ୍ସେସ ଦେଇଛନ୍ତି"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"ଡ୍ରାଇଭ କରିବା ସମୟରେ ଆପଣ <xliff:g id="APP">%2$s</xliff:g>କୁ <xliff:g id="COUNT">%1$d</xliff:g>ଟି ଅନୁମତି ଦେଇଛନ୍ତି"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{ଡ୍ରାଇଭ କରିବା ସମୟରେ ଆପଣ <xliff:g id="APP_0">%1$s</xliff:g> ଓ #ଟି ଅନ୍ୟ ଆପକୁ ଆକ୍ସେସ ଦେଇଛନ୍ତି}other{ଡ୍ରାଇଭ କରିବା ସମୟରେ ଆପଣ <xliff:g id="APP_1">%1$s</xliff:g> ଓ #ଟି ଅନ୍ୟ ଆପକୁ ଆକ୍ସେସ ଦେଇଛନ୍ତି}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"ସେଟିଂସକୁ ଯାଆନ୍ତୁ"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"କିଛି ଆପକୁ କିଛି ମାସ ହେଲା ବ୍ୟବହାର କରାଯାଇନାହିଁ"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"କାଢ଼ି ଦିଆଯାଇଥିବା ଅନୁମତିଗୁଡ଼ିକ"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"ଅନୁମତିଗୁଡ଼ିକୁ କାଢ଼ି ଦିଆଯାଇଛି"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"ଆପଣଙ୍କର ଫୋନ୍‌‌ର କଲ୍‌ ଲଗ୍‌ ଆକ୍ସେସ୍‌ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ କି?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଫୋନ୍‍ କଲ୍‍ କରିବାକୁ ତଥା ପରିଚାଳନା କରିବାକୁ ଅନୁମତି ଦେବେ କି?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଆପଣଙ୍କ ଗୁରୁତ୍ୱପୂର୍ଣ୍ଣ ଲକ୍ଷଣଗୁଡ଼ିକ ବିଷୟରେ ସେନ୍ସର୍‍ ଡାଟା ଆକ୍ସେସ୍‍ କରିବା ପାଇଁ ଅନୁମତି ଦେବେ କି?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"ଆପଣ ଆପ ବ୍ୟବହାର କରୁନଥିଲେ ମଧ୍ୟ, ଏହି ଆପ ସବୁ ସମୟରେ ଆପଣଙ୍କ ମହତ୍ତ୍ୱପୂର୍ଣ୍ଣ ଲକ୍ଷଣଗୁଡ଼ିକ ବିଷୟରେ ସେନ୍ସର ଡାଟାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ ଚାହେଁ। "<annotation id="link">"ସେଟିଂସରେ ଅନୁମତି ଦିଅନ୍ତୁ।"</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"ଆପଣ ଆପ ବ୍ୟବହାର କରୁନଥିଲେ ମଧ୍ୟ, ଏହି ଆପ ସବୁ ସମୟରେ ଆପଣଙ୍କ ମହତ୍ତ୍ୱପୂର୍ଣ୍ଣ ଲକ୍ଷଣଗୁଡ଼ିକ ବିଷୟରେ ସେନ୍ସର ଡାଟାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ ଚାହେଁ। ଏହି ପରିବର୍ତ୍ତନ କରିବାକୁ, "<annotation id="link">"ସେଟିଂସକୁ ଯାଆନ୍ତୁ।"</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"ଆପଣଙ୍କ ମହତ୍ତ୍ୱପୂର୍ଣ୍ଣ ଲକ୍ଷଣଗୁଡ଼ିକ ବିଷୟରେ ସେନ୍ସର ଡାଟାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ କି?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"ଆପଣ ଆପ ବ୍ୟବହାର କରୁନଥିଲେ ମଧ୍ୟ, ଏହି ଆପ ସବୁ ସମୟରେ ଆପଣଙ୍କ ମହତ୍ତ୍ୱପୂର୍ଣ୍ଣ ଲକ୍ଷଣଗୁଡ଼ିକ ବିଷୟରେ ସେନ୍ସର ଡାଟା ଆକ୍ସେସ କରିବାକୁ ଚାହିଁପାରେ। "<annotation id="link">"ସେଟିଂସରେ ଅନୁମତି ଦିଅନ୍ତୁ।"</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ପାଇଁ ଆପଣଙ୍କ ମହତ୍ତ୍ୱପୂର୍ଣ୍ଣ ଲକ୍ଷଣଗୁଡ଼ିକ ବିଷୟରେ ସେନ୍ସର ଡାଟାକୁ ଆକ୍ସେସ ପରିବର୍ତ୍ତନ କରିବେ କି?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"ଆପଣ ଆପ ବ୍ୟବହାର କରୁନଥିଲେ ମଧ୍ୟ, ବଡି ସେନ୍ସର ଡାଟାକୁ ସର୍ବଦା ଆକ୍ସେସ କରିବା ନିମନ୍ତେ ଏହି ଆପକୁ ଅନୁମତି ଦେବା ପାଇଁ, "<annotation id="link">"ସେଟିଂସକୁ ଯାଆନ୍ତୁ।"</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"ଆପ ବ୍ୟବହାରରେ ଥିବା ସମୟରେ ବଡି ସେନ୍ସର ଡାଟାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବା ଜାରି ରଖିବେ?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"ଆପଣଙ୍କୁ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ପଠାଇବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"ଆପଣଙ୍କୁ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ପଠାଇବା ଜାରି ରଖିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"ନିୟନ୍ତ୍ରିତ ଅନୁରୋଧଗୁଡ଼ିକ"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"କ୍ୟାମେରା ଅନୁମତି କାଢ଼ି ଦିଅନ୍ତୁ"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"ମାଇକ୍ରୋଫୋନ ଅନୁମତି କାଢ଼ି ଦିଅନ୍ତୁ"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"ସେବା ପରିଚାଳନା କରନ୍ତୁ"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"ଅନୁମତିଗୁଡ଼ିକୁ ପରିଚାଳନା କରନ୍ତୁ"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"ଫୋନ କଲ ଦ୍ୱାରା ବ୍ୟବହାର କରାଯାଉଛି"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"ଏବେ ଫୋନ କଲରେ ବ୍ୟବହାର କରାଯାଇଛି"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> ଦ୍ୱାରା ବ୍ୟବହାର କରାଯାଉଛି"</string>
diff --git a/PermissionController/res/values-pa/strings.xml b/PermissionController/res/values-pa/strings.xml
index d431f2853..7d2465b16 100644
--- a/PermissionController/res/values-pa/strings.xml
+++ b/PermissionController/res/values-pa/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"<xliff:g id="APP">%1$s</xliff:g> ਦੀਆਂ ਸਾਰੀਆਂ ਇਜਾਜ਼ਤਾਂ ਦੇਖੋ"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"ਇਸ ਇਜਾਜ਼ਤ ਵਾਲੀਆਂ ਸਾਰੀਆਂ ਐਪਾਂ ਦੇਖੋ"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Assistant ਦੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਦੀ ਵਰਤੋਂ ਦਿਖਾਓ"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"ਅਣਵਰਤੀ ਐਪ ਦੀਆਂ ਸੈਟਿੰਗਾਂ"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"ਐਪ ਨੂੰ ਨਾ ਵਰਤੇ ਜਾਣ \'ਤੇ ਇਸ ਲਈ ਦਿੱਤੀਆਂ ਇਜਾਜ਼ਤਾਂ ਨੂੰ ਹਟਾ ਦਿਓ"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"ਇਜਾਜ਼ਤਾਂ ਹਟਾਓ ਅਤੇ ਜਗ੍ਹਾ ਖਾਲੀ ਕਰੋ"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"ਤੁਹਾਡੀ ਡਾਟਾ ਸੁਰੱਖਿਆ ਲਈ, ਜੇ ਇਹ ਐਪ ਕੁਝ ਮਹੀਨਿਆਂ ਲਈ ਵਰਤੀ ਨਹੀਂ ਗਈ, ਤਾਂ ਇਸ ਐਪ ਲਈ ਇਜਾਜ਼ਤਾਂ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"ਤੁਹਾਡੀ ਡਾਟਾ ਸੁਰੱਖਿਆ ਲਈ, ਜੇ ਇਹ ਐਪ ਕੁਝ ਮਹੀਨਿਆਂ ਲਈ ਵਰਤੀ ਨਹੀਂ ਗਈ, ਤਾਂ ਅੱਗੇ ਦਿੱਤੀਆਂ ਇਜਾਜ਼ਤਾਂ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"ਤੁਹਾਡੀ ਡਾਟਾ ਸੁਰੱਖਿਆ ਲਈ, ਜੋ ਐਪਾਂ ਤੁਸੀਂ ਕੁਝ ਮਹੀਨਿਆਂ ਤੋਂ ਨਹੀਂ ਵਰਤੀਆਂ ਉਹਨਾਂ ਐਪਾਂ ਤੋਂ ਇਜਾਜ਼ਤਾਂ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਗਿਆ ਹੈ।"</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"ਗੱਡੀ ਚਲਾਉਂਦੇ ਸਮੇਂ, ਤੁਸੀਂ <xliff:g id="APP">%1$s</xliff:g> ਨੂੰ <xliff:g id="PERMISSION_1">%2$s</xliff:g> ਅਤੇ <xliff:g id="PERMISSION_2">%3$s</xliff:g> ਤੱਕ ਪਹੁੰਚ ਦਿੱਤੀ ਹੈ"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"ਗੱਡੀ ਚਲਾਉਂਦੇ ਸਮੇਂ, ਤੁਸੀਂ <xliff:g id="APP">%2$s</xliff:g> ਨੂੰ <xliff:g id="COUNT">%1$d</xliff:g> ਇਜਾਜ਼ਤਾਂ ਦਿੱਤੀਆਂ ਹਨ"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{ਗੱਡੀ ਚਲਾਉਂਦੇ ਸਮੇਂ, ਤੁਸੀਂ <xliff:g id="APP_0">%1$s</xliff:g> ਅਤੇ # ਹੋਰ ਐਪ ਨੂੰ ਪਹੁੰਚ ਦਿੱਤੀ ਹੈ}one{ਗੱਡੀ ਚਲਾਉਂਦੇ ਸਮੇਂ, ਤੁਸੀਂ <xliff:g id="APP_1">%1$s</xliff:g> ਅਤੇ # ਹੋਰ ਐਪ ਨੂੰ ਪਹੁੰਚ ਦਿੱਤੀ ਹੈ}other{ਗੱਡੀ ਚਲਾਉਂਦੇ ਸਮੇਂ, ਤੁਸੀਂ <xliff:g id="APP_1">%1$s</xliff:g> ਅਤੇ # ਹੋਰ ਐਪਾਂ ਨੂੰ ਪਹੁੰਚ ਦਿੱਤੀ ਹੈ}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"ਸੈਟਿੰਗਾਂ \'ਤੇ ਜਾਓ"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"ਕੁਝ ਐਪਾਂ ਨੂੰ ਕਈ ਮਹੀਨਿਆਂ ਤੋਂ ਵਰਤਿਆ ਨਹੀਂ ਗਿਆ"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"ਹਟਾਈਆਂ ਗਈਆਂ ਇਜਾਜ਼ਤਾਂ"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"ਇਜਾਜ਼ਤਾਂ ਨੂੰ ਹਟਾਇਆ ਗਿਆ"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਦੇ ਕਾਲ ਲੌਗਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਫ਼ੋਨ ਕਾਲਾਂ ਕਰਨ ਅਤੇ ਉਹਨਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਦੇਣਾ ਹੈ?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਤੁਹਾਡੇ ਸਰੀਰ ਦੇ ਅਹਿਮ ਲੱਛਣਾਂ ਸੰਬੰਧੀ ਸੈਂਸਰ ਡਾਟੇ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"ਇਸ ਐਪ ਨੂੰ ਹਰ ਵੇਲੇ ਤੁਹਾਡੇ ਸਰੀਰ ਦੇ ਅਹਿਮ ਲੱਛਣਾਂ ਸੰਬੰਧੀ ਸੈਂਸਰ ਡਾਟੇ ਤੱਕ ਪਹੁੰਚ ਚਾਹੀਦੀ ਹੈ, ਭਾਵੇਂ ਤੁਸੀਂ ਐਪ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੇ ਹੋ ਜਾਂ ਨਾ। "<annotation id="link">"ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਆਗਿਆ ਦਿਓ।"</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"ਇਸ ਐਪ ਨੂੰ ਹਰ ਵੇਲੇ ਤੁਹਾਡੇ ਸਰੀਰ ਦੇ ਅਹਿਮ ਲੱਛਣਾਂ ਸੰਬੰਧੀ ਸੈਂਸਰ ਡਾਟੇ ਤੱਕ ਪਹੁੰਚ ਚਾਹੀਦੀ ਹੈ, ਭਾਵੇਂ ਤੁਸੀਂ ਐਪ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੇ ਹੋ ਜਾਂ ਨਹੀਂ। ਇਹ ਤਬਦੀਲੀ ਕਰਨ ਲਈ, "<annotation id="link">"ਸੈਟਿੰਗਾਂ \'ਤੇ ਜਾਓ।"</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਤੁਹਾਡੇ ਸਰੀਰ ਦੇ ਅਹਿਮ ਲੱਛਣਾਂ ਸੰਬੰਧੀ ਸੈਂਸਰ ਡਾਟੇ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"ਸ਼ਾਇਦ ਇਸ ਐਪ ਨੂੰ ਹਰ ਵੇਲੇ ਤੁਹਾਡੇ ਸਰੀਰ ਦੇ ਅਹਿਮ ਲੱਛਣਾਂ ਸੰਬੰਧੀ ਸੈਂਸਰ ਡਾਟੇ ਤੱਕ ਪਹੁੰਚ ਹੋਵੇ, ਭਾਵੇਂ ਤੁਸੀਂ ਐਪ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੇ ਹੋ ਜਾਂ ਨਾ। "<annotation id="link">"ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਆਗਿਆ ਦਿਓ।"</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਦੇ ਲਈ ਤੁਹਾਡੇ ਸਰੀਰ ਦੇ ਅਹਿਮ ਲੱਛਣਾਂ ਸੰਬੰਧੀ ਸੈਂਸਰ ਡਾਟੇ ਤੱਕ ਪਹੁੰਚ ਬਦਲਣੀ ਹੈ?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"ਇਸ ਐਪ ਨੂੰ ਹਰ ਸਮੇਂ ਸਰੀਰ ਸੰਬੰਧੀ ਸੈਂਸਰ ਦੇ ਡਾਟੇ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣ ਲਈ, ਭਾਵੇਂ ਤੁਸੀਂ ਐਪ ਦੀ ਵਰਤੋਂ ਨਾ ਕਰ ਰਹੇ ਹੋਵੋ, "<annotation id="link">"ਸੈਟਿੰਗਾਂ \'ਤੇ ਜਾਓ।"</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"ਕੀ ਐਪ ਦੇ ਵਰਤੋਂ ਵਿੱਚ ਹੋਣ ਵੇਲੇ ਸਰੀਰ ਸੰਬੰਧੀ ਸੈਂਸਰ ਦੇ ਡਾਟੇ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣ ਲਈ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਆਗਿਆ ਦੇ ਕੇ ਰੱਖਣੀ ਹੈ?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਤੁਹਾਨੂੰ ਸੂਚਨਾਵਾਂ ਭੇਜਣ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਤੁਹਾਨੂੰ ਸੂਚਨਾਵਾਂ ਭੇਜਣਾ ਜਾਰੀ ਰੱਖਣ ਦੇਣਾ ਹੈ?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"ਨਿਯੰਤਰਿਤ ਇਜਾਜ਼ਤਾਂ"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"ਕੈਮਰਾ ਇਜਾਜ਼ਤ ਹਟਾਓ"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਇਜਾਜ਼ਤ ਹਟਾਓ"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"ਸੇਵਾ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"ਇਜਾਜ਼ਤਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"ਫ਼ੋਨ ਕਾਲ ਦੁਆਰਾ ਵਰਤਿਆ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"ਹਾਲ ਹੀ ਵਿੱਚ ਫ਼ੋਨ ਕਾਲ ਵਿੱਚ ਵਰਤਿਆ ਗਿਆ"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਵੱਲੋਂ ਵਰਤਿਆ ਜਾ ਰਿਹਾ ਹੈ"</string>
diff --git a/PermissionController/res/values-pl/strings.xml b/PermissionController/res/values-pl/strings.xml
index 711535949..17d5b965e 100644
--- a/PermissionController/res/values-pl/strings.xml
+++ b/PermissionController/res/values-pl/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Zobacz wszystkie uprawnienia aplikacji <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Wyświetl wszystkie aplikacje z tym uprawnieniem"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Pokaż użycie mikrofonu w Asystencie"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Nieużywane ustawienia aplikacji"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Usuń uprawnienia, jeśli aplikacja jest nieużywana"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Usuń uprawnienia i zwolnij miejsce"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Aby chronić Twoje dane, usuniemy uprawnienia tej aplikacji, jeśli nie była używana od kilku miesięcy."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Aby chronić Twoje dane, jeśli aplikacja nie będzie używana przez kilka miesięcy, usuniemy te uprawnienia: <xliff:g id="PERMS">%1$s</xliff:g>."</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Aby chronić Twoje dane, usunęliśmy uprawnienia aplikacji, których nie używano od kilku miesięcy."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Podczas jazdy przyznałeś(-aś) aplikacji <xliff:g id="APP">%1$s</xliff:g> te uprawnienia: <xliff:g id="PERMISSION_1">%2$s</xliff:g> i <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Podczas jazdy przyznałeś(-aś) uprawnienia (<xliff:g id="COUNT">%1$d</xliff:g>) aplikacji <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Podczas jazdy przyznałeś(-aś) uprawnienia aplikacji <xliff:g id="APP_0">%1$s</xliff:g> i # innej aplikacji}few{Podczas jazdy przyznałeś(-aś) uprawnienia aplikacji <xliff:g id="APP_1">%1$s</xliff:g> i # innym aplikacjom}many{Podczas jazdy przyznałeś(-aś) uprawnienia aplikacji <xliff:g id="APP_1">%1$s</xliff:g> i # innym aplikacjom}other{Podczas jazdy przyznałeś(-aś) uprawnienia aplikacji <xliff:g id="APP_1">%1$s</xliff:g> i # innej aplikacji}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Otwórz Ustawienia"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Niektóre aplikacje nie były używane od kilku miesięcy"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Usunięte uprawnienia"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Usunięto uprawnienia"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na dostęp do rejestrów połączeń?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na wykonywanie połączeń telefonicznych i zarządzanie nimi?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na dostęp do danych z czujnika podstawowych funkcji życiowych?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Aplikacja chce mieć dostęp do danych z czujnika podstawowych funkcji życiowych przez cały czas, nawet gdy jej nie używasz. "<annotation id="link">"Zezwól w ustawieniach"</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Ta aplikacja chce mieć dostęp do danych z czujnika dotyczących parametrów życiowych przez cały czas, nawet kiedy jej nie używasz. Aby dokonać tej zmiany, "<annotation id="link">"otwórz ustawienia."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na dostęp do danych z czujnika podstawowych funkcji życiowych?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Aplikacja chce mieć dostęp do danych z czujnika podstawowych funkcji życiowych przez cały czas, nawet gdy jej nie używasz. "<annotation id="link">"Zezwól w ustawieniach"</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Zmienić dostęp aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; do danych z czujnika podstawowych funkcji życiowych?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Aby zezwolić tej aplikacji na dostęp do danych z czujników na ciele przez cały czas, nawet kiedy jej nie używasz, "<annotation id="link">"przejdź do ustawień"</annotation>"."</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Czy nadal zezwalać aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na dostęp do czujników na ciele podczas jej używania?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na wysyłanie powiadomień?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na dalsze wysyłanie powiadomień?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Pozwolenia kontrolowane"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Usuń uprawnienia dotyczące aparatu"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Usuń uprawnienia dotyczące mikrofonu"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Zarządzaj usługą"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Zarządzanie uprawnieniami"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Używane przez rozmowę telefoniczną"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Ostatnio używane przez rozmowę telefoniczną"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Używane przez aplikację <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-pt-rBR/strings.xml b/PermissionController/res/values-pt-rBR/strings.xml
index c96e1cbf2..eaffb2483 100644
--- a/PermissionController/res/values-pt-rBR/strings.xml
+++ b/PermissionController/res/values-pt-rBR/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Ver todas as permissões do app <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Ver todos os apps que têm esta permissão"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Mostrar uso de microfone pelo Assistente"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Configurações de apps não usados"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Remover permissões se o app não for usado"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Remover permissões e liberar espaço"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Para proteger seus dados, as permissões serão removidas se o app não for usado por alguns meses."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Para proteger seus dados, se o app não for usado por alguns meses, as seguintes permissões serão removidas: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Para proteger seus dados, as permissões de apps que não foram usados nos últimos meses foram removidas."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Enquanto dirigia, você deu ao app <xliff:g id="APP">%1$s</xliff:g> acesso à permissão de <xliff:g id="PERMISSION_1">%2$s</xliff:g> e <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Enquanto dirigia, você concedeu <xliff:g id="COUNT">%1$d</xliff:g> permissões ao app <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Enquanto dirigia, você concedeu acesso ao <xliff:g id="APP_0">%1$s</xliff:g> e # outro app}one{Enquanto dirigia, você concedeu acesso ao <xliff:g id="APP_1">%1$s</xliff:g> e # outro app}other{Enquanto dirigia, você concedeu acesso ao <xliff:g id="APP_1">%1$s</xliff:g> e # outros apps}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Ir para Configurações"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Alguns apps não foram usados nos últimos meses"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Permissões removidas"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Permissões removidas"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse seu registro de chamadas telefônicas?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; gerencie e faça chamadas telefônicas?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse os dados do sensor sobre seus sinais vitais?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Este app quer acessar os dados do sensor sobre seus sinais vitais o tempo todo, mesmo quando não estiver em uso. "<annotation id="link">"Permita nas configurações."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Este app quer acessar os dados do sensor sobre seus sinais vitais o tempo todo, mesmo quando não estiver em uso. Para fazer essa mudança, "<annotation id="link">"acesse as configurações"</annotation>"."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse os dados do sensor sobre seus sinais vitais?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Este app pode querer acessar os dados do sensor sobre seus sinais vitais o tempo todo, mesmo quando não estiver em uso. "<annotation id="link">"Permita nas configurações."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Mudar o acesso de &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aos dados do sensor sobre seus sinais vitais?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Para permitir que o app tenha acesso a dados do sensor corporal a qualquer momento, mesmo quando não estiver em uso, "<annotation id="link">"acesse as configurações"</annotation>"."</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Continuar permitindo que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse dados do sensor corporal enquanto estiver em uso?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; envie notificações?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; continue a enviar notificações?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Permissões controladas"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Remover permissão da câmera"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Remover permissão do microfone"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Gerenciar serviço"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Gerenciar permissões"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Em uso pela chamada telefônica"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Usada recentemente em uma chamada telefônica"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Em uso por <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-pt-rPT/strings.xml b/PermissionController/res/values-pt-rPT/strings.xml
index 386f0bcc1..4f8c1af09 100644
--- a/PermissionController/res/values-pt-rPT/strings.xml
+++ b/PermissionController/res/values-pt-rPT/strings.xml
@@ -61,7 +61,7 @@
<string name="auto_permission_manager_summary" msgid="9157438376234301354">"Faça a gestão do acesso aos dados do calendário, registos de chamadas e mais"</string>
<string name="granted_permission_decision" msgid="7824827491551861365">"Concedeu o acesso à app <xliff:g id="APP_NAME">%1$s</xliff:g> a <xliff:g id="PERMISSION_NAME">%2$s</xliff:g>"</string>
<string name="denied_permission_decision" msgid="5308961501779563781">"Negou o acesso da app <xliff:g id="APP_NAME">%1$s</xliff:g> a <xliff:g id="PERMISSION_NAME">%2$s</xliff:g>"</string>
- <string name="days_ago" msgid="6650359081551335629">"{count,plural, =0{Hoje}=1{Há 1 dia}one{Há # dia(s)}other{Há # dias}}"</string>
+ <string name="days_ago" msgid="6650359081551335629">"{count,plural, =0{Hoje}=1{Há 1 dia}other{Há # dias}}"</string>
<string name="app_disable_dlg_positive" msgid="7418444149981904940">"Desativar app"</string>
<string name="app_disable_dlg_text" msgid="3126943217146120240">"Se desativar esta app, o Android e outras apps podem deixar de funcionar corretamente. Não se esqueça de que não pode eliminar esta app por ter sido pré-instalada no dispositivo. Ao desativá-la, irá ocultá-la no dispositivo."</string>
<string name="app_permission_manager" msgid="3903811137630909550">"Gestor de autorizações"</string>
@@ -69,7 +69,7 @@
<string name="no_permissions" msgid="3881676756371148563">"Sem autorizações"</string>
<string name="additional_permissions" msgid="5801285469338873430">"Autorizações adicionais"</string>
<string name="app_permissions_info_button_label" msgid="7633312050729974623">"Abrir informações da app"</string>
- <string name="additional_permissions_more" msgid="5681220714755304407">"{count,plural, =1{Mais #}one{# more}other{Mais #}}"</string>
+ <string name="additional_permissions_more" msgid="5681220714755304407">"{count,plural, =1{Mais #}other{Mais #}}"</string>
<string name="old_sdk_deny_warning" msgid="2382236998845153919">"Esta app foi concebida para uma versão mais antiga do Android. Recusar a autorização pode fazer com que deixe de funcionar como pretendido."</string>
<string name="storage_supergroup_warning_allow" msgid="103093462784523190">"Esta app foi concebida para uma versão mais antiga do Android. Se conceder esta autorização, será autorizado o acesso a todo o armazenamento (incluindo fotos, vídeos, música, áudio e outros ficheiros)."</string>
<string name="storage_supergroup_warning_deny" msgid="6420765672683284347">"Esta app foi concebida para uma versão mais antiga do Android. Se recusar esta autorização, será recusado o acesso a todo o armazenamento (incluindo fotos, vídeos, música, áudio e outros ficheiros)."</string>
@@ -134,10 +134,10 @@
<string name="auto_permission_usage_timeline_summary" msgid="2713135806453218703">"<xliff:g id="ACCESS_TIME">%1$s</xliff:g> • <xliff:g id="SUMMARY_TEXT">%2$s</xliff:g>"</string>
<string name="history_preference_subtext_2" msgid="1521763591164293683">"<xliff:g id="APP_NAME">%1$s</xliff:g> • <xliff:g id="TRUNCATED_TIME">%2$s</xliff:g>"</string>
<string name="history_preference_subtext_3" msgid="758761785983094351">"<xliff:g id="ATTRIBUTION_NAME">%1$s</xliff:g> • <xliff:g id="APP_NAME">%2$s</xliff:g> • <xliff:g id="TRUNCATED_TIME">%3$s</xliff:g>"</string>
- <string name="duration_used_days" msgid="8293010131040301793">"{count,plural, =1{1 dia}one{# dia(s)}other{# dias}}"</string>
- <string name="duration_used_hours" msgid="1128716208752263576">"{count,plural, =1{1 hora}one{# hora(s)}other{# horas}}"</string>
- <string name="duration_used_minutes" msgid="5335824115042576567">"{count,plural, =1{1 min}one{# min}other{# min}}"</string>
- <string name="duration_used_seconds" msgid="6543746449171675028">"{count,plural, =1{1 s}one{# s}other{# s}}"</string>
+ <string name="duration_used_days" msgid="8293010131040301793">"{count,plural, =1{1 dia}other{# dias}}"</string>
+ <string name="duration_used_hours" msgid="1128716208752263576">"{count,plural, =1{1 hora}other{# horas}}"</string>
+ <string name="duration_used_minutes" msgid="5335824115042576567">"{count,plural, =1{1 min}other{# min}}"</string>
+ <string name="duration_used_seconds" msgid="6543746449171675028">"{count,plural, =1{1 s}other{# s}}"</string>
<string name="permission_usage_any_permission" msgid="6358023078298106997">"Qualquer autorização"</string>
<string name="permission_usage_any_time" msgid="3802087027301631827">"Em qualquer altura"</string>
<string name="permission_usage_last_7_days" msgid="7386221251886130065">"Últimos 7 dias"</string>
@@ -158,9 +158,9 @@
<string name="permission_usage_bar_chart_title_last_hour" msgid="6571647509660009185">"Utilização das autorizações na última hora"</string>
<string name="permission_usage_bar_chart_title_last_15_minutes" msgid="2743143675412824819">"Utilização das autorizações nos últimos 15 minutos"</string>
<string name="permission_usage_bar_chart_title_last_minute" msgid="820450867183487607">"Utilização das autorizações no último minuto"</string>
- <string name="permission_usage_preference_summary_not_used_24h" msgid="3087783232178611025">"Não utilizada nas últimas 24 horas"</string>
+ <string name="permission_usage_preference_summary_not_used_24h" msgid="3087783232178611025">"Não utilizado nas últimas 24 horas"</string>
<string name="permission_usage_preference_summary_not_used_7d" msgid="4592301300810120096">"Não utilizada nos últimos 7 dias"</string>
- <string name="permission_usage_preference_label" msgid="8343167938128676378">"{count,plural, =1{Utilizadas por 1 app}one{Utilizadas por # app(s)}other{Utilizadas por # apps}}"</string>
+ <string name="permission_usage_preference_label" msgid="8343167938128676378">"{count,plural, =1{Utilizadas por 1 app}other{Utilizadas por # apps}}"</string>
<string name="permission_usage_view_details" msgid="6675335735468752787">"Ver tudo no painel de controlo"</string>
<string name="app_permission_usage_filter_label" msgid="7182861154638631550">"Filtrado por: <xliff:g id="PERM">%1$s</xliff:g>"</string>
<string name="app_permission_usage_remove_filter" msgid="2926157607436428207">"Remover filtro"</string>
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Ver todas as autorizações da app <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Ver todas as apps com esta autorização"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Mostrar utilização do microfone do assistente"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Definições de apps não usadas"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Remover autorizações se a app não for utilizada"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Remover autorizações e libertar espaço"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Para proteger os seus dados, as autorizações desta app serão removidas se a mesma não for utilizada durante alguns meses."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Para proteger os seus dados, se a app não for utilizada há alguns meses, serão removidas as seguintes autorizações: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Para proteger os seus dados, foram removidas as autorizações para as apps que não utiliza há alguns meses."</string>
@@ -247,25 +252,24 @@
<string name="denied_header" msgid="903209608358177654">"Não permitidas"</string>
<string name="storage_footer_warning_text" msgid="2242258357752432337">"Algumas apps que fornecem funcionalidades essenciais do seu dispositivo podem ter um acesso especial aos seus ficheiros"</string>
<string name="storage_footer_hyperlink_text" msgid="7759955324552930974">"Veja as apps com acesso a todos os ficheiros"</string>
- <string name="days" msgid="609563020985571393">"{count,plural, =1{1 dia}one{# dia(s)}other{# dias}}"</string>
- <string name="hours" msgid="3447767892295843282">"{count,plural, =1{1 hora}one{# hora(s)}other{# horas}}"</string>
- <string name="minutes" msgid="4408293038068503157">"{count,plural, =1{1 minuto}one{# minuto(s)}other{# minutos}}"</string>
- <string name="seconds" msgid="5397771912131132690">"{count,plural, =1{1 segundo}one{# segundo(s)}other{# segundos}}"</string>
+ <string name="days" msgid="609563020985571393">"{count,plural, =1{1 dia}other{# dias}}"</string>
+ <string name="hours" msgid="3447767892295843282">"{count,plural, =1{1 hora}other{# horas}}"</string>
+ <string name="minutes" msgid="4408293038068503157">"{count,plural, =1{1 minuto}other{# minutos}}"</string>
+ <string name="seconds" msgid="5397771912131132690">"{count,plural, =1{1 segundo}other{# segundos}}"</string>
<string name="permission_reminders" msgid="6528257957664832636">"Lembretes de autorização"</string>
<string name="auto_revoke_permission_reminder_notification_title_one" msgid="6690347469376854137">"1 app não utilizada"</string>
<string name="auto_revoke_permission_reminder_notification_title_many" msgid="6062217713645069960">"<xliff:g id="NUMBER_OF_APPS">%s</xliff:g> apps não utilizadas"</string>
<string name="auto_revoke_permission_reminder_notification_content" msgid="4492228990462107487">"Autorizações removidas para proteger a sua privacidade. Toque para rever."</string>
<string name="auto_revoke_permission_notification_title" msgid="2629844160853454657">"Autorizações removidas para apps não utilizadas"</string>
<string name="auto_revoke_permission_notification_content" msgid="5125990886047799375">"Algumas apps não são utilizadas há alguns meses. Toque para rever."</string>
- <string name="unused_apps_notification_title" msgid="4314832015894238019">"{count,plural, =1{# app não utilizada}one{# app(s) não utilizada(s)}other{# apps não utilizadas}}"</string>
+ <string name="unused_apps_notification_title" msgid="4314832015894238019">"{count,plural, =1{# app não utilizada}other{# apps não utilizadas}}"</string>
<string name="unused_apps_notification_content" msgid="9195026773244581246">"As autorizações e os ficheiros temporários foram removidos e as notificações foram interrompidas. Toque para rever."</string>
<string name="post_drive_permission_decision_reminder_title" msgid="1290697371418139976">"Verifique as autorizações recentes"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_1_permission" msgid="670521503734140711">"Durante a condução, deu à app <xliff:g id="APP">%1$s</xliff:g> acesso à autorização de <xliff:g id="PERMISSION">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Durante a condução, deu à app <xliff:g id="APP">%1$s</xliff:g> acesso à autorização de <xliff:g id="PERMISSION_1">%2$s</xliff:g> e <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Durante a condução, concedeu <xliff:g id="COUNT">%1$d</xliff:g> autorizações à app <xliff:g id="APP">%2$s</xliff:g>"</string>
- <string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Durante a condução, deu acesso à app <xliff:g id="APP_0">%1$s</xliff:g> e a mais # app}one{Durante a condução, deu acesso à app <xliff:g id="APP_1">%1$s</xliff:g> e a mais # app(s)}other{Durante a condução, deu acesso à app <xliff:g id="APP_1">%1$s</xliff:g> e a mais # apps}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Durante a condução, deu acesso à app <xliff:g id="APP_0">%1$s</xliff:g> e a mais # app}other{Durante a condução, deu acesso à app <xliff:g id="APP_1">%1$s</xliff:g> e a mais # apps}}"</string>
+ <string name="go_to_settings" msgid="1053735612211228335">"Aceder às Definições"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Algumas apps não são utilizadas há alguns meses."</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Autorizações removidas"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Autorizações removidas"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aceda aos registos de chamadas do seu telemóvel?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; faça e gira chamadas telefónicas?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aceda aos dados do sensor acerca dos seus sinais vitais?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Esta app pretende aceder sempre aos dados de sensores sobre os seus sinais vitais, mesmo quando não a estiver a usar. "<annotation id="link">"Permita-o nas definições."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Esta app quer aceder sempre aos dados de sensores sobre os seus sinais vitais, mesmo quando não a estiver a usar. Para fazer esta alteração, "<annotation id="link">"aceda às definições."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aceda aos dados de sensores acerca dos seus sinais vitais?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Esta app pode pretender aceder sempre aos dados de sensores sobre os seus sinais vitais, mesmo quando não a estiver a usar. "<annotation id="link">"Permita-o nas definições."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Alterar o acesso aos dados de sensores sobre os seus sinais vitais para a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Para permitir que esta app aceda sempre aos dados de sensores de corpo, mesmo quando não está a ser usada, "<annotation id="link">"aceda às definições."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Continuar a permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aceda aos dados de sensores de corpo enquanto usa a app?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; lhe envie notificações?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; continue a enviar-lhe notificações?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Autorizações controladas"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Remover autorização da câmara"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Remover autorização do microfone"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Gerir serviço"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Gerir autorizações"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Em utilização pela chamada telefónica"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Utilizado recentemente na chamada telefónica"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Em utilização pela app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-pt/strings.xml b/PermissionController/res/values-pt/strings.xml
index c96e1cbf2..eaffb2483 100644
--- a/PermissionController/res/values-pt/strings.xml
+++ b/PermissionController/res/values-pt/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Ver todas as permissões do app <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Ver todos os apps que têm esta permissão"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Mostrar uso de microfone pelo Assistente"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Configurações de apps não usados"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Remover permissões se o app não for usado"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Remover permissões e liberar espaço"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Para proteger seus dados, as permissões serão removidas se o app não for usado por alguns meses."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Para proteger seus dados, se o app não for usado por alguns meses, as seguintes permissões serão removidas: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Para proteger seus dados, as permissões de apps que não foram usados nos últimos meses foram removidas."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Enquanto dirigia, você deu ao app <xliff:g id="APP">%1$s</xliff:g> acesso à permissão de <xliff:g id="PERMISSION_1">%2$s</xliff:g> e <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Enquanto dirigia, você concedeu <xliff:g id="COUNT">%1$d</xliff:g> permissões ao app <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Enquanto dirigia, você concedeu acesso ao <xliff:g id="APP_0">%1$s</xliff:g> e # outro app}one{Enquanto dirigia, você concedeu acesso ao <xliff:g id="APP_1">%1$s</xliff:g> e # outro app}other{Enquanto dirigia, você concedeu acesso ao <xliff:g id="APP_1">%1$s</xliff:g> e # outros apps}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Ir para Configurações"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Alguns apps não foram usados nos últimos meses"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Permissões removidas"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Permissões removidas"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse seu registro de chamadas telefônicas?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; gerencie e faça chamadas telefônicas?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse os dados do sensor sobre seus sinais vitais?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Este app quer acessar os dados do sensor sobre seus sinais vitais o tempo todo, mesmo quando não estiver em uso. "<annotation id="link">"Permita nas configurações."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Este app quer acessar os dados do sensor sobre seus sinais vitais o tempo todo, mesmo quando não estiver em uso. Para fazer essa mudança, "<annotation id="link">"acesse as configurações"</annotation>"."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse os dados do sensor sobre seus sinais vitais?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Este app pode querer acessar os dados do sensor sobre seus sinais vitais o tempo todo, mesmo quando não estiver em uso. "<annotation id="link">"Permita nas configurações."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Mudar o acesso de &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aos dados do sensor sobre seus sinais vitais?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Para permitir que o app tenha acesso a dados do sensor corporal a qualquer momento, mesmo quando não estiver em uso, "<annotation id="link">"acesse as configurações"</annotation>"."</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Continuar permitindo que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse dados do sensor corporal enquanto estiver em uso?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; envie notificações?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; continue a enviar notificações?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Permissões controladas"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Remover permissão da câmera"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Remover permissão do microfone"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Gerenciar serviço"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Gerenciar permissões"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Em uso pela chamada telefônica"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Usada recentemente em uma chamada telefônica"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Em uso por <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-ro/strings.xml b/PermissionController/res/values-ro/strings.xml
index 1b4d2fb66..6ebb25caa 100644
--- a/PermissionController/res/values-ro/strings.xml
+++ b/PermissionController/res/values-ro/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Vedeți toate permisiunile aplicației <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Vedeți toate aplicațiile cu această permisiune"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Afișează datele de utilizare a microfonului cu Asistentul"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Setările aplicațiilor nefolosite"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Eliminați permisiunile dacă aplicația nu este folosită"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Revocă permisiunile și eliberează spațiu"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Pentru a vă proteja datele, se vor elimina permisiunile pentru această aplicație dacă nu este folosită câteva luni."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Pentru a vă proteja datele, dacă aplicația nu este folosită câteva luni, se vor elimina următoarele permisiuni: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Pentru a vă proteja datele, s-au eliminat permisiunile din aplicațiile pe care nu le-ați folosit de câteva luni."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"În timpul condusului ați permis accesul <xliff:g id="APP">%1$s</xliff:g> la <xliff:g id="PERMISSION_1">%2$s</xliff:g> și la <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"În timpul condusului ați acordat <xliff:g id="COUNT">%1$d</xliff:g> permisiuni pentru <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{În timpul condusului ați permis accesul pentru <xliff:g id="APP_0">%1$s</xliff:g> și # altă aplicație}few{În timpul condusului ați permis accesul pentru <xliff:g id="APP_1">%1$s</xliff:g> și # alte aplicații}other{În timpul condusului ați permis accesul pentru <xliff:g id="APP_1">%1$s</xliff:g> și # de alte aplicații}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Accesați Setări"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Unele aplicații nu au fost folosite de câteva luni"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Permisiuni eliminate"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Permisiuni eliminate"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Permiteți &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să vă acceseze jurnalele de apeluri?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Permiteți &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să inițieze și să gestioneze apeluri telefonice?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Permiteți &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să acceseze datele de la senzori despre semnele dvs. vitale?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Aplicația solicită acces permanent la datele de la senzori despre semne vitale, chiar și când nu o folosiți. "<annotation id="link">"Acordați această permisiune din setări."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Aplicația solicită acces permanent la datele de la senzori despre semnele vitale, chiar și când nu o folosiți. Pentru a face această modificare, "<annotation id="link">"accesați setările"</annotation>"."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Permiteți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să acceseze datele de la senzori despre semnele dvs. vitale?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Aplicația poate să solicite acces permanent la datele de la senzori despre semne vitale, chiar și când nu o folosiți. "<annotation id="link">"Acordați permisiunea din setări"</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Schimbați permisiunea de acces la datele de la senzori despre semnele vitale pentru &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Pentru a permite accesul permanent al aplicației la datele de la senzorii corporali, chiar și atunci când nu o folosiți, "<annotation id="link">"accesați setările"</annotation>"."</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Permiteți în continuare accesul &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; la datele de la senzorii corporali în timpul folosirii aplicației?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Permiteți &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să vă trimită notificări?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Permiteți &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să continue să vă trimită notificări?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Permisiuni controlate"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Eliminați permisiunea pentru cameră"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Eliminați permisiunea pentru microfon"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Gestionați serviciul"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Gestionați permisiunile"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Este folosit de un apel telefonic"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Folosit recent într-un apel telefonic"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Este folosit de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-ru/strings.xml b/PermissionController/res/values-ru/strings.xml
index f58a0a80e..fe443c5b2 100644
--- a/PermissionController/res/values-ru/strings.xml
+++ b/PermissionController/res/values-ru/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Все разрешения приложения \"<xliff:g id="APP">%1$s</xliff:g>\""</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Все приложения с этим разрешением"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Показывать сведения об использовании микрофона Ассистентом"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Настройки неиспользуемых приложений"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Отзывать разрешения, если приложение не используется"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Удалять разрешения и освобождать место"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Для защиты ваших данных мы отзовем разрешения, предоставленные этому приложению, если вы не будете пользоваться им несколько месяцев."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Если вы не будете пользоваться приложением несколько месяцев, в целях защиты ваших данных мы отзовем следующие разрешения: <xliff:g id="PERMS">%1$s</xliff:g>."</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"В целях защиты ваших данных мы отозвали разрешения для приложений, которыми вы не пользовались несколько месяцев."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Во время вождения вы предоставили приложению \"<xliff:g id="APP">%1$s</xliff:g>\" следующие разрешения: <xliff:g id="PERMISSION_1">%2$s</xliff:g> и <xliff:g id="PERMISSION_2">%3$s</xliff:g>."</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Во время вождения вы предоставили приложению \"<xliff:g id="APP">%2$s</xliff:g>\" несколько разрешений (<xliff:g id="COUNT">%1$d</xliff:g>)."</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Во время вождения вы предоставили разрешение для \"<xliff:g id="APP_0">%1$s</xliff:g>\" и ещё # приложения.}one{Во время вождения вы предоставили разрешение для \"<xliff:g id="APP_1">%1$s</xliff:g>\" и ещё # приложения.}few{Во время вождения вы предоставили разрешение для \"<xliff:g id="APP_1">%1$s</xliff:g>\" и ещё # приложений.}many{Во время вождения вы предоставили разрешение для \"<xliff:g id="APP_1">%1$s</xliff:g>\" и ещё # приложений.}other{Во время вождения вы предоставили разрешение для \"<xliff:g id="APP_1">%1$s</xliff:g>\" и ещё # приложения.}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Открыть настройки"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Вы уже несколько месяцев не используете некоторые приложения."</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Приложения, у которых отозваны разрешения"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Разрешения отозваны"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к списку вызовов?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; совершать звонки и управлять ими?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к данным датчиков о состоянии организма?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Этому приложению требуется доступ к данным нательных датчиков, даже когда вы им не пользуетесь. Предоставьте разрешение в "<annotation id="link">"настройках"</annotation>"."</string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Этому приложению требуется доступ к данным нательных датчиков, даже когда вы им не пользуетесь. Предоставить разрешение можно в "<annotation id="link">"настройках"</annotation>"."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Разрешить приложению \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" доступ к данным датчиков на теле?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Этому приложению может потребоваться доступ к данным нательных датчиков, даже когда вы им не пользуетесь. Предоставьте разрешение в "<annotation id="link">"настройках"</annotation>"."</string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Изменить разрешение на доступ к данным нательных датчиков для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Чтобы предоставить приложению доступ к данным нательных датчиков, даже когда вы им не пользуетесь, "<annotation id="link">"измените настройки"</annotation>"."</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Предоставить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к данным нательных датчиков, когда оно используется?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Разрешить \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" отправлять уведомления?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Разрешить приложению \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" и дальше отправлять уведомления?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Контролируемые разрешения"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Закрыть доступ к камере"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Закрыть доступ к микрофону"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Настроить сервис"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Управление разрешениями"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Используется во время телефонного звонка"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Недавно использовалось во время телефонного звонка"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Используется приложением \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
diff --git a/PermissionController/res/values-si/strings.xml b/PermissionController/res/values-si/strings.xml
index 7ee508c21..ed87835c7 100644
--- a/PermissionController/res/values-si/strings.xml
+++ b/PermissionController/res/values-si/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"සියලුම <xliff:g id="APP">%1$s</xliff:g> අවසර බලන්න"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"මෙම අවසරය සහිත සියලුම යෙදුම් බලන්න"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"සහායක මයික්‍රෆෝන භාවිතය පෙන්වන්න"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"භාවිත නොකළ යෙදුම් සැකසීම්"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"යෙදුම භාවිත කර නැති නම් අවසර ඉවත් කරන්න"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"අවසර ඉවත් කරන්න සහ ඉඩ හිස් කරන්න"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"ඔබගේ දත්ත ආරක්ෂා කිරීම සඳහා, යෙදුම මාස කිහිපයක් භාවිතා නොකරන්නේ නම් මෙම යෙදුම සඳහා අවසර ඉවත් කරනු ලැබේ."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"ඔබගේ දත්ත ආරක්ෂා කිරීම සඳහා, යෙදුම මාස කිහිපයක් භාවිතා නොකරන්නේ නම් පහත අවසර ඉවත් කරනු ලැබේ: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"ඔබේ දත්ත ආරක්ෂා කිරීමට, ඔබ මාස කීපයක් තුළ භාවිත කර නැති යෙදුම්වලින් අවසර ඉවත් කර ඇත"</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"ධාවනය අතරතුර, ඔබ <xliff:g id="APP">%1$s</xliff:g> ප්‍රවේශයට <xliff:g id="PERMISSION_1">%2$s</xliff:g> සහ <xliff:g id="PERMISSION_2">%3$s</xliff:g> දුන්නේය"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"ධාවනය අතරතුර, ඔබ <xliff:g id="APP">%2$s</xliff:g> හට අවසර <xliff:g id="COUNT">%1$d</xliff:g>ක් දුන්නේය"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{ධාවනය අතරතුර, ඔබ <xliff:g id="APP_0">%1$s</xliff:g> සහ තවත් යෙදුම් #කට ප්‍රවේශය දුන්නේය}one{ධාවනය අතරතුර, ඔබ <xliff:g id="APP_1">%1$s</xliff:g> සහ තවත් යෙදුම් #කට ප්‍රවේශය දුන්නේය}other{ධාවනය අතරතුර, ඔබ <xliff:g id="APP_1">%1$s</xliff:g> සහ තවත් යෙදුම් #කට ප්‍රවේශය දුන්නේය}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"සැකසීම් වෙත යන්න"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"සමහර යෙදුම් මාස කිහිපයක් තුළ භාවිත කර නැත"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"ඉවත් කළ අවසර"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"අවසර ඉවත් කළ"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; ඔබේ ඇමතුම් ලොග වෙත පිවිසීමට ඉඩ දෙන්නද?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; වෙත දුරකථන ඇමතුම් ලබා ගැනීමට සහ කළමනාකරණය කිරීමට ඉඩ දෙන්නද?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; වෙත ඔබගේ ජෛව ලක්ෂණ පිළිබඳ සංවේදක දත්ත වෙත ප්‍රවේශ වීමට ඉඩ දෙන්නද?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"මෙම යෙදුමට ඔබ යෙදුම භාවිත නොකරමින් සිටින විට පවා, සියලු අවස්ථාවල ඔබගේ ජෛව ලක්ෂණ පිළිබඳ සංවේදක දත්තවලට ප්‍රවේශය අවශ්‍යයි. "<annotation id="link">"සැකසීම් තුළ ඉඩ දෙන්න."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"මෙම යෙදුමට ඔබ යෙදුම භාවිත නොකරමින් සිටින විට පවා, සියලු අවස්ථාවල ඔබගේ ජෛව ලක්ෂණ පිළිබඳ සංවේදක දත්තවලට ප්‍රවේශය අවශ්‍යයි. මෙම වෙනස් කිරීම සිදු කිරීමට, "<annotation id="link">"සැකසීම් වෙත යන්න."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; හට ඔබගේ ජෛව ලක්ෂණ පිළිබඳ සංවේදක දත්ත වෙත ප්‍රවේශ වීමට ඉඩ දෙන්නද?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"මෙම යෙදුමට සෑම විටම ඔබගේ ජෛව ලක්ෂණ පිළිබඳ සංවේදක දත්තවලට ප්‍රවේශ වීමට අවශ්‍ය විය හැකිය. "<annotation id="link">"සැකසීම් තුළ ඉඩ දෙන්න."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"ඔබගේ ජජව ලක්ෂණ පිළිබඳ දත්ත වෙත ප්‍රවේශය <xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා වෙනස් කරන්නද?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"ඔබ යෙදුම භාවිත නොකරන විට පවා, මෙම යෙදුමට ශරීර සංවේදක දත්තවලට ප්‍රවේශ වීමට ඉඩ දීමට, "<annotation id="link">"සැකසීම් වෙත යන්න "</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"යෙදුම භාවිතයේ ඇති අතරතුර ශරීර සංවේදක දත්ත වෙත ප්‍රවේශ වීමට &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; හට ඉඩ දෙන්නද?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"ඔබට දැනුම්දීම් එවීමට &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; හට ඉඩ දෙන්නද?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"ඔබට දැනුම්දීම් එවීම දිගටම සිදු කිරීමට &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; හට ඉඩ දෙන්නද?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"පාලිත අවසර"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"කැමරා අවසරය ඉවත් කරන්න"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"මයික්‍රෆෝන අවසරය ඉවත් කරන්න"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"සේවය කළමනාකරණය කරන්න"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"අවසර කළමනාකරණය කරන්න"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"දුරකථන ඇමතුම මගින් භාවිත කරමින් ඇත"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"දුරකථන ඇමතුම තුළ මෑතකදී භාවිත කරන ලදී"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> මගින් භාවිත කරමින් ඇත"</string>
diff --git a/PermissionController/res/values-sk/strings.xml b/PermissionController/res/values-sk/strings.xml
index a22007ce1..0c4bdefa0 100644
--- a/PermissionController/res/values-sk/strings.xml
+++ b/PermissionController/res/values-sk/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Zobraziť všetky povolenia aplikácie <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Zobraziť všetky aplikácie s týmto povolením"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Zobraziť používanie mikrofónu Asistentom"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Nastavenia nepoužívaných aplikácií"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Odstrániť povolenia, ak sa aplikácia nepoužíva"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Odstraňovať povol. a uvoľňovať priestor"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Ak túto aplikáciu niekoľko mesiacov nepoužijete, v záujme ochrany vašich údajov budú odstránené jej povolenia."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Ak túto aplikáciu niekoľko mesiacov nepoužijete, v záujme ochrany vašich údajov budú odstránené tieto povolenia: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"V záujme ochrany vašich údajov boli odobrané povolenia aplikáciám, ktoré ste niekoľko mesiacov nepoužívali."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Počas jazdy ste udelili aplikácii <xliff:g id="APP">%1$s</xliff:g> prístup k povoleniam <xliff:g id="PERMISSION_1">%2$s</xliff:g> &amp; <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Počas jazdy ste udelili aplikácii <xliff:g id="APP">%2$s</xliff:g> tento počet povolení: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Počas jazdy ste udelili prístup aplikácii <xliff:g id="APP_0">%1$s</xliff:g> a # ďalšej}few{Počas jazdy ste udelili prístup aplikácii <xliff:g id="APP_1">%1$s</xliff:g> a # ďalším}many{While driving, you gave <xliff:g id="APP_1">%1$s</xliff:g> &amp; # other apps access}other{Počas jazdy ste udelili prístup aplikácii <xliff:g id="APP_1">%1$s</xliff:g> a # ďalším}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Prejsť do Nastavení"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Niektoré aplikácie neboli niekoľko mesiacov používané"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Odstránené povolenia"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Povolenia boli odstránené"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prístup k zoznamu tel. hovorov?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uskutočňovať a spravovať telefonické hovory?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; používať údaje senzorov o vašich životných funkciách?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Táto aplikácia požaduje nepretržitý prístup k dátam senzorov o vašich životných funkciách, aj keď ju nepoužívate. "<annotation id="link">"Povolíte ho v nastaveniach."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Táto aplikácia požaduje nepretržitý prístup k dátam senzorov o vašich životných funkciách, a to aj vtedy, keď ju nepoužívate. Povolíte to "<annotation id="link">"v nastaveniach"</annotation>"."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; používať dáta senzorov o vašich životných funkciách?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Táto aplikácia môže požadovať nepretržitý prístup k dátam senzorov o vašich životných funkciách, aj keď ju nepoužívate. "<annotation id="link">"Povolíte ho v nastaveniach."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Chcete zmeniť prístup aplikácie &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; k dátam senzorov o vašich životných funkciách?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Ak chcete tejto aplikácii povoliť nepretržitý prístup k údajom telového senzora, a to aj v prípade, že ju nepoužívate, "<annotation id="link">"prejdite do nastavení."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prístup k dátam telových senzorov počas jej používania?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; posielať vám upozornenia?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; posielať vám ďalej upozornenia?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Ovládané povolenia"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Odstrániť povolenie pre kameru"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Odstrániť povolenie pre mikrofón"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Spravovať službu"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Správy povolení"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Využíva telefonický hovor"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Nedávno využil telefonický hovor"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Využíva aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-sl/strings.xml b/PermissionController/res/values-sl/strings.xml
index 0a1f884be..e7854ef6d 100644
--- a/PermissionController/res/values-sl/strings.xml
+++ b/PermissionController/res/values-sl/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Ogled vseh dovoljenj za aplikacijo <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Ogled vseh aplikacij s tem dovoljenjem"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Prikaz uporabe pomožnega mikrofona"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Nastavitve neuporabljenih aplikacij"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Odstrani dovoljenja, če aplikacija ni v uporabi"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Odstrani dovoljenja in sprosti prostor"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Z namenom zaščite podatkov bodo dovoljenja za to aplikacijo odstranjena, če je več mesecev ne boste uporabljali."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Če aplikacije več mesecev ne boste uporabljali, bodo z namenom zaščite podatkov odstranjena ta dovoljenja: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Z namenom zaščite podatkov so bila odstranjena dovoljenja za aplikacije, ki jih več mesecev niste uporabljali."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Med vožnjo ste aplikaciji <xliff:g id="APP">%1$s</xliff:g> odobrili dostop do teh dovoljenj: <xliff:g id="PERMISSION_1">%2$s</xliff:g> in <xliff:g id="PERMISSION_2">%3$s</xliff:g>."</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Med vožnjo ste aplikaciji <xliff:g id="APP">%2$s</xliff:g> odobrili toliko dovoljenj: <xliff:g id="COUNT">%1$d</xliff:g>."</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Med vožnjo ste odobrili dostop aplikaciji <xliff:g id="APP_0">%1$s</xliff:g> in še # aplikaciji.}one{Med vožnjo ste odobrili dostop aplikaciji <xliff:g id="APP_1">%1$s</xliff:g> in še # aplikaciji.}two{Med vožnjo ste odobrili dostop aplikaciji <xliff:g id="APP_1">%1$s</xliff:g> in še # aplikacijam.}few{Med vožnjo ste odobrili dostop aplikaciji <xliff:g id="APP_1">%1$s</xliff:g> in še # aplikacijam.}other{Med vožnjo ste odobrili dostop aplikaciji <xliff:g id="APP_1">%1$s</xliff:g> in še # aplikacijam.}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Odpri nastavitve"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Nekatere aplikacije niso bile uporabljene več mesecev"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Odstranjena dovoljenja"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Dovoljenja so bila odstranjena"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Dovolite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dostop do dnevnikov klicev v telefonu?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Dovolite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; opravljanje in upravljanje telefonskih klicev?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Dovolite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dostop do podatkov tipala o vitalnih znakih?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Ta aplikacija želi vseskozi dostopati do podatkov tipal o vitalnih znakih, tudi ko aplikacije ne uporabljate. "<annotation id="link">"To omogočite v nastavitvah."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Ta aplikacija želi stalen dostop do podatkov tipal vitalnih znakov, tudi ko aplikacije ne uporabljate. Če želite izvesti to spremembo, "<annotation id="link">"pojdite v nastavitve"</annotation>"."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; omogočiti dostop do podatkov tipal o vitalnih znakih?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Ta aplikacija bo morda želela vseskozi dostopati do podatkov tipal o vitalnih znakih, tudi ko aplikacije ne uporabljate. "<annotation id="link">"To omogočite v nastavitvah."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Želite spremeniti dostop do podatkov tipal o vitalnih znakih za aplikacijo &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Če želite tej aplikaciji omogočiti stalen dostop do podatkov tipal telesnih funkcij, tudi ko je ne uporabljate, "<annotation id="link">"pojdite v nastavitve"</annotation>"."</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Ali želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; še naprej dovoliti dostop do podatkov tipal telesnih funkcij, ko je v uporabi?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; omogočiti, da vam pošilja obvestila?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; omogočiti, da vam še naprej pošilja obvestila?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Zunanje upravljana dovoljenja"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Odstrani dovoljenje za fotoaparat"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Odstrani dovoljenje za mikrofon"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Upravljanje storitve"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Upravljanje dovoljenj"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Trenutno se uporablja v telefonskem klicu"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Nedavno uporabljeno v telefonskem klicu"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Trenutno uporablja aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-sq/strings.xml b/PermissionController/res/values-sq/strings.xml
index 848a17e4d..071046d21 100644
--- a/PermissionController/res/values-sq/strings.xml
+++ b/PermissionController/res/values-sq/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Shiko të gjitha lejet e aplikacionit \"<xliff:g id="APP">%1$s</xliff:g>\""</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Shiko të gjitha aplikacionet me këtë leje"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Shfaq përdorimin e mikrofonit të \"Asistentit\""</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Cilësimet e aplikacioneve të papërdorura"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Hiq lejet nëse aplikacioni nuk është përdorur"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Hiq lejet dhe liro hapësirën"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Për të mbrojtur të dhënat e tua, lejet për këtë aplikacion do të hiqen nëse aplikacioni nuk përdoret për disa muaj."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Për të mbrojtur të dhënat e tua, nëse aplikacioni nuk është përdorur për disa muaj, lejet e mëposhtme do të hiqen: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Për të mbrojtur të dhënat e tua, lejet janë hequr nga aplikacionet që nuk i ke përdorur për disa muaj."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Gjatë drejtimit të makinës, i ke dhënë <xliff:g id="APP">%1$s</xliff:g> qasje në <xliff:g id="PERMISSION_1">%2$s</xliff:g> dhe <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Gjatë drejtimit të makinës, i ke dhënë <xliff:g id="COUNT">%1$d</xliff:g> leje <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Gjatë drejtimit të makinës, i ke dhënë qasje <xliff:g id="APP_0">%1$s</xliff:g> dhe # aplikacioni tjetër}other{Gjatë drejtimit të makinës, i ke dhënë qasje <xliff:g id="APP_1">%1$s</xliff:g> dhe # aplikacioneve të tjera}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Shko te \"Cilësimet\""</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Disa aplikacione nuk janë përdorur për disa muaj"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Me leje të hequra"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Leje të hequra"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Të lejohet &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të ketë qasje në evidencat e tua të telefonatave?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të kryejë dhe të menaxhojë telefonata?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të ketë qasje te të dhënat e sensorëve rreth shenjave të tua jetësore?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Aplikacioni kërkon qasje te të dhënat e sensorëve rreth shenjave të tua jetësore gjithmonë, edhe kur nuk e përdor aplikacionin. "<annotation id="link">"Lejo te cilësimet."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Aplikacioni kërkon qasje te të dhënat e sensorëve rreth shenjave të tua jetësore gjithmonë, edhe kur nuk e përdor aplikacionin. Për ta bërë këtë ndryshim, "<annotation id="link">"shko te cilësimet."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të ketë qasje te të dhënat e sensorëve rreth shenjave të tua jetësore?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Aplikacioni mund të kërkojë qasje te të dhënat e sensorëve rreth shenjave jetësore, edhe nëse nuk e përdor aplikacionin. "<annotation id="link">"Lejo te cilësimet."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Të ndryshohet qasja te të dhënat e sensorëve rreth shenjave të tua jetësore për &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Për të lejuar këtë aplikacion që të ketë qasje te të dhënat e sensorit të trupit gjithmonë, edhe kur nuk e përdor aplikacionin, "<annotation id="link">"shko te cilësimet."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Të lejohet akoma që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të ketë qasje te të dhënat e sensorit të trupit kur aplikacioni përdoret?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të të dërgojë njoftime?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të vazhdojë të të dërgojë njoftime?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Lejet e kontrolluara"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Hiq lejen e kamerës"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Hiq lejen e mikrofonit"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Menaxho shërbimin"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Menaxho lejet"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Po përdoret nga telefonata"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Përdorur së fundi në telefonatë"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Po përdoret nga <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-sr/strings.xml b/PermissionController/res/values-sr/strings.xml
index 688f953e5..32848afff 100644
--- a/PermissionController/res/values-sr/strings.xml
+++ b/PermissionController/res/values-sr/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Прикажи све дозволе за: <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Прикажи све апликације са овом дозволом"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Прикажи како Помоћник користи микрофон"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Подешавања некоришћених апликација"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Уклони дозволе ако се апликација не користи"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Уклони дозволе и ослободи простор"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Ради заштите података, дозволе за ову апликацију се уклањају ако се апликација не користи пар месеци."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Ради заштите података, следеће дозволе се уклањају ако се апликација не користи пар месеци: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Ради заштите података, дозволе су уклоњене из апликација које нисте користили пар месеци."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Током вожње сте дали апликацији <xliff:g id="APP">%1$s</xliff:g> приступ дозволама <xliff:g id="PERMISSION_1">%2$s</xliff:g> и <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Током вожње сте дали дозволе (<xliff:g id="COUNT">%1$d</xliff:g>) апликацији <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Током вожње сте омогућили приступ за <xliff:g id="APP_0">%1$s</xliff:g> и још # другу апликацију}one{Током вожње сте омогућили приступ за <xliff:g id="APP_1">%1$s</xliff:g> и још # апликацију}few{Током вожње сте омогућили приступ за <xliff:g id="APP_1">%1$s</xliff:g> и још # апликације}other{Током вожње сте омогућили приступ за <xliff:g id="APP_1">%1$s</xliff:g> и још # апликација}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Иди у Подешавања"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Неке апликације нису коришћене пар месеци"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Уклоњене дозволе"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Уклоњене дозволе"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Желите да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; приступа евиденцијама позива на телефону?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Желите да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; упућује позиве и управља њима?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Желите да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;приступа подацима сензора о виталним функцијама?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Ова апликација жели да приступа подацима сензора о виталним функцијама све време, чак и када не користите апликацију. "<annotation id="link">"Дозволите у подешавањима."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Ова апликација жели да све време приступа подацима сензора о виталним функцијама, чак и када не користите апликацију. Да бисте обавили ову измену, "<annotation id="link">"идите у подешавања."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Желите да омогућите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; приступа подацима сензора о виталним функцијама?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Ова апликација можда жели да све време приступа подацима сензора о виталним функцијама чак и када не користите апликацију."<annotation id="link">"Дозволите у подешавањима."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Желите да промените приступ подацима сензора о виталним функцијама за &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Да бисте дозволили овој апликацији да све време приступа подацима сензора за тело, чак и када не користите апликацију, "<annotation id="link">"идите у подешавања."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Желите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; и даље приступа подацима сензора за тело док се апликација користи?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Желите да дозволите да вам &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; шаље обавештења?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Желите да дозволите да вам &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; и даље шаље обавештења?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Контролисане дозволе"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Уклони дозволу за камеру"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Уклони дозволу за микрофон"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Управљајте услугом"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Управљајте дозволама"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Користи га телефонски позив"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Недавно коришћено у телефонском позиву"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Користи апликација <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-sv/strings.xml b/PermissionController/res/values-sv/strings.xml
index 9cf5c22eb..5f2406a24 100644
--- a/PermissionController/res/values-sv/strings.xml
+++ b/PermissionController/res/values-sv/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Visa alla behörigheter för <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Visa alla appar med den här behörigheten"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Visa mikrofonanvändning för assistenten"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Inställningar för appar som inte används"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Ta bort behörigheter om en app inte används"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Ta bort behörigheter och frigör utrymme"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Behörigheter tas bort av säkerhetsskäl från den här appen om den inte används på några månader."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Följande behörigheter tas bort av säkerhetsskäl från appen om den inte används på några månader: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Behörigheter har tagits bort av säkerhetsskäl från appar som inte har använts på några månader."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Du gav <xliff:g id="APP">%1$s</xliff:g> åtkomst till <xliff:g id="PERMISSION_1">%2$s</xliff:g> och <xliff:g id="PERMISSION_2">%3$s</xliff:g> medan du körde"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Du beviljade <xliff:g id="APP">%2$s</xliff:g> <xliff:g id="COUNT">%1$d</xliff:g> behörigheter medan du körde"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Du gav <xliff:g id="APP_0">%1$s</xliff:g> och # annan app åtkomst medan du körde}other{Du gav <xliff:g id="APP_1">%1$s</xliff:g> och # andra appar åtkomst medan du körde}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Öppna inställningarna"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Vissa appar har inte använts på några månader"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Borttagna behörigheter"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Behörigheter har tagits bort"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; åtkomst till samtalsloggarna?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; behörighet att ringa och hantera telefonsamtal?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; åtkomst till sensordata om vitalparametrar?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Appen vill ha åtkomst till sensordata om vitalparametrar hela tiden, även när du inte använder den. "<annotation id="link">"Tillåt i inställningarna."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Appen vill ha åtkomst till sensordata om vitalparametrar hela tiden, även när du inte använder den. "<annotation id="link">"Öppna inställningarna"</annotation>" om du vill tillåta detta."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; åtkomstbehörighet till sensordata om vitalparametrar?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Appen kan vilja ha åtkomst till sensordata om vitalparametrar hela tiden, även när du inte använder den. "<annotation id="link">"Tillåt i inställningarna."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Vill du ändra åtkomstbehörigheten till sensordata om vitalparametrar för &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783"><annotation id="link">"Öppna inställningarna"</annotation>" om du vill ge appen åtkomst till data från kroppssensorer hela tiden, även när du inte använder appen."</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Ska &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ha åtkomst till data från kroppssensorer medan appen används även i fortsättningen?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; behörighet att skicka aviseringar?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; behörighet att fortsätta skicka aviseringar?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Styrda behörigheter"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Ta bort kamerabehörighet"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Ta bort mikrofonbehörighet"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Hantera tjänst"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Hantera behörigheter"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Används just nu av telefonsamtal"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Användes nyligen av telefonsamtal"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Används just nu av <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-sw/strings.xml b/PermissionController/res/values-sw/strings.xml
index 10291945f..16ac2dc1f 100644
--- a/PermissionController/res/values-sw/strings.xml
+++ b/PermissionController/res/values-sw/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Angalia ruhusa zote za <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Angalia programu zote zenye ruhusa hii"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Onyesha matumizi ya maikrofoni ya mratibu"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Mipangilio ya programu zisizotumika"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Ondoa ruhusa ikiwa programu haitumiki"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Ondoa ruhusa na upate nafasi"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Ili kulinda data yako, ruhusa za programu hii zitaondolewa programu isipotumika kwa miezi michache."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Ili kulinda data yako, programu isipotumika kwa miezi michache, ruhusa zifuatazo zitaondolewa: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Ili kulinda data yako, ruhusa zimeondolewa kwenye programu ambazo hujatumia kwa miezi michache."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Wakati wa kuendesha, uliipa <xliff:g id="APP">%1$s</xliff:g> uwezo wa kufikia <xliff:g id="PERMISSION_1">%2$s</xliff:g> na <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Wakati wa kuendesha, uliipa <xliff:g id="APP">%2$s</xliff:g> ruhusa <xliff:g id="COUNT">%1$d</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Ulipokuwa ukiendesha gari, uliipa <xliff:g id="APP_0">%1$s</xliff:g> na programu nyingine # ruhusa ya kufikia}other{Ulipokuwa ukiendesha gari, uliipa <xliff:g id="APP_1">%1$s</xliff:g> na programu zingine # ruhusa ya kufikia}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Nenda kwenye Mipangilio"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Baadhi ya programu hazijatumiwa kwa miezi michache"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Zilizoondolewa ruhusa"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Zilizoondolewa ruhusa"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Ungependa kuiruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie rekodi zako za nambari za simu?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Ungependa kuruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; kupiga na kudhibiti simu?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Ungependa kuiruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie data ya vitambuzi kuhusu viashiria muhimu vya mwili wako?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Programu hii inataka kufikia data ya vitambuzi inayohusu viashiria muhimu vya mwili wako kila wakati, hata wakati huitumii."<annotation id="link">"Iruhusu katika mipangilio."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Programu hii inataka kufikia data ya vitambuzi kuhusu viashiria muhimu vya mwili wako kila wakati, hata wakati huitumii. Ili ufanye mabadiliko haya, "<annotation id="link">"nenda kwenye mipangilio."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Ungependa kuruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie data ya vitambuzi inayohusu viashiria muhimu vya mwili wako?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Huenda programu hii ikataka kufikia data ya vitambuzi inayohusu viashiria muhimu vya mwili wako kila wakati, hata wakati huitumii."<annotation id="link">"Iruhusu katika mipangilio."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Ungependa kubadilisha ufikiaji wa data ya vitambuzi inayohusu viashiria muhimu vya mwili wako kwenye &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Ili uruhusu programu hii ifikie data ya vitambuzi shughuli za mwili kila wakati, hata wakati hutumii programu, "<annotation id="link">"nenda kwenye mipangilio."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Ungependa kuendelea kuruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie data ya vitambuzi shughuli za mwili wakati programu inatumika?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Ungependa kuruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ikutumie arifa?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Ungependa kuruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; iendelee kukutumia arifa?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Ruhusa zinazodhibitiwa"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Ondoa ruhusa ya kamera"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Ondoa ruhusa ya maikrofoni"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Dhibiti huduma"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Dhibiti ruhusa"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Inatumiwa na simu"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Ilitumiwa hivi karibuni kwenye simu"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Inatumiwa na <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-ta/strings.xml b/PermissionController/res/values-ta/strings.xml
index d11e8752b..d763b4c06 100644
--- a/PermissionController/res/values-ta/strings.xml
+++ b/PermissionController/res/values-ta/strings.xml
@@ -196,8 +196,14 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"அனைத்து <xliff:g id="APP">%1$s</xliff:g> அனுமதிகளையும் காட்டு"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"இந்த அனுமதியைக் கொண்டுள்ள அனைத்து ஆப்ஸையும் காட்டு"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"அசிஸ்டண்ட் மைக்ரோஃபோன் உபயோகத்தைக் காட்டு"</string>
+ <!-- no translation found for unused_apps_category_title (2988455616845243901) -->
+ <skip />
<string name="auto_revoke_label" msgid="5068393642936571656">"இந்த ஆப்ஸ் பயன்படுத்தப்படவில்லை என்றால் அனுமதிகளை அகற்றவும்"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"அனுமதிகளை அகற்றி இடத்தைக் காலியாக்கு"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"இந்த ஆப்ஸைச் சில மாதங்கள் பயன்படுத்தவில்லை என்றால் உங்கள் தரவைப் பாதுகாப்பதற்காக இதற்கான அனுமதிகள் அகற்றப்படும்."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"இந்த ஆப்ஸைச் சில மாதங்கள் பயன்படுத்தவில்லை என்றால் உங்கள் தரவைப் பாதுகாப்பதற்காக பின்வரும் அனுமதிகள் அகற்றப்படும்: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"உங்கள் தரவைப் பாதுகாப்பதற்காக, கடந்த சில மாதங்களில் நீங்கள் பயன்படுத்தாத ஆப்ஸில் இருந்து அனுமதிகள் அகற்றப்பட்டன."</string>
@@ -264,8 +270,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"வாகனம் ஓட்டும்போது <xliff:g id="PERMISSION_1">%2$s</xliff:g> &amp; <xliff:g id="PERMISSION_2">%3$s</xliff:g> அணுகலை <xliff:g id="APP">%1$s</xliff:g> ஆப்ஸுக்கு வழங்கியுள்ளீர்கள்"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"வாகனம் ஓட்டும்போது <xliff:g id="APP">%2$s</xliff:g> ஆப்ஸுக்கு <xliff:g id="COUNT">%1$d</xliff:g> அனுமதிகளை வழங்கியுள்ளீர்கள்"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{வாகனம் ஓட்டும்போது <xliff:g id="APP_0">%1$s</xliff:g> ஆப்ஸ் &amp; # பிற ஆப்ஸுக்கு அணுகலை வழங்கியுள்ளீர்கள்}other{வாகனம் ஓட்டும்போது <xliff:g id="APP_1">%1$s</xliff:g> ஆப்ஸ் &amp; # பிற ஆப்ஸுக்கு அணுகலை வழங்கியுள்ளீர்கள்}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"அமைப்புகளுக்குச் செல்"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"கடந்த சில மாதங்களாக சில ஆப்ஸ் பயன்படுத்தப்படவில்லை"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"அனுமதிகள் அகற்றப்பட்டவை"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"அனுமதிகள் அகற்றப்பட்டவை"</string>
@@ -468,10 +473,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"உங்கள் மொபைல் அழைப்புப் பதிவுகளை அணுக, &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"மொபைல் அழைப்புகள் செய்யவும், அவற்றை நிர்வகிக்கவும், &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"உங்கள் உடலியக்கக் குறிகள் பற்றிய சென்சார் தரவை அணுகுவதற்கு &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"இந்த ஆப்ஸை உபயோகிக்காதபோதும்கூட எந்நேரமும் உடலியக்க அளவீடுகள் பற்றிய சென்சார் தரவை அணுக அனுமதி கேட்கும். "<annotation id="link">"அமைப்புகளில் அனுமதிக்கவும்."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"ஆப்ஸைப் பயன்படுத்தாதபோதும் உங்கள் உடலியக்க அளவீடுகள் பற்றிய சென்சார் தரவை எப்போதும் அணுக இந்த ஆப்ஸ் விரும்புகிறது. இந்த மாற்றத்தைச் செய்ய "<annotation id="link">"அமைப்புகளுக்குச் செல்லுங்கள்."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"உடலியக்க அளவீடுகள் பற்றிய சென்சார் தரவை அணுக &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"இந்த ஆப்ஸை உபயோகிக்காதபோதும்கூட எந்நேரமும் உடலியக்க அளவீடுகள் பற்றிய சென்சார் தரவை அணுக அனுமதி கேட்கக்கூடும். "<annotation id="link">"அமைப்புகளில் அனுமதிக்கவும்."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸுக்கு உங்கள் உடலியக்க அளவீடுகள் பற்றிய சென்சார் தரவின் அணுகலை மாற்றவா?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"ஆப்ஸைப் பயன்படுத்தாதபோதும் இந்த ஆப்ஸ் எல்லா நேரங்களிலும் உடல் சென்சார் தரவை அணுக "<annotation id="link">"அமைப்புகளுக்குச் செல்லுங்கள்."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"ஆப்ஸ் பயன்பாட்டில் இருக்கும்போது உடல் சென்சார் தரவை அணுக &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&amp;gt ஆப்ஸுக்குத் தொடர்ந்து அனுமதியளிக்கவா?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"உங்களுக்கு அறிவிப்புகளை அனுப்ப &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"உங்களுக்குத் தொடர்ந்து அறிவிப்புகளை அனுப்ப &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"கட்டுப்படுத்தப்பட்ட அனுமதிகள்"</string>
@@ -509,6 +514,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"கேமரா அனுமதியை அகற்று"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"மைக்ரோஃபோன் அனுமதியை அகற்று"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"சேவையை நிர்வகியுங்கள்"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"அனுமதிகளை நிர்வகியுங்கள்"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"மொபைல் அழைப்பால் பயன்படுத்தப்படுகிறது"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"மொபைல் அழைப்பால் சமீபத்தில் பயன்படுத்தப்பட்டது"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸால் பயன்படுத்தப்படுகிறது"</string>
diff --git a/PermissionController/res/values-te/strings.xml b/PermissionController/res/values-te/strings.xml
index 097952d37..81b79c09f 100644
--- a/PermissionController/res/values-te/strings.xml
+++ b/PermissionController/res/values-te/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"అన్ని \'<xliff:g id="APP">%1$s</xliff:g>\' అనుమతులను చూడండి"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"ఈ అనుమతి ఉన్న అన్ని యాప్‌లను చూడండి"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"అసిస్టెంట్ మైక్రోఫోన్ వినియోగాన్ని చూపు"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"ఉపయోగించని యాప్ సెట్టింగ్‌లు"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"యాప్‌ని ఉపయోగించకపోతే, అనుమతులను తీసివేయండి"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"అనుమతులను తీసివేసి స్పేస్‌ను ఖాళీ చేయండి"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"మీ డేటాను సురక్షితంగా ఉంచడానికి, ఈ యాప్ కొన్ని నెలలుగా వినియోగంలో లేకుంటే, దాని అనుమతులు తీసివేయబడతాయి."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"మీ డేటాను సురక్షితంగా ఉంచడానికి, ఈ యాప్ కొన్ని నెలలుగా వినియోగంలో లేకుంటే, దానికి ఇచ్చిన కింది అనుమతులు తీసివేయబడతాయి: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"మీ డేటాను సురక్షితంగా ఉంచడానికి, కొన్ని నెలలుగా వినియోగంలో లేని యాప్‌ల అనుమతులు తీసివేయబడ్డాయి."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"డ్రైవింగ్‌లో ఉన్నప్పుడు, మీరు <xliff:g id="APP">%1$s</xliff:g> యాప్‌నకు <xliff:g id="PERMISSION_1">%2$s</xliff:g>, <xliff:g id="PERMISSION_2">%3$s</xliff:g>‌కు యాక్సెస్‌ను ఇచ్చారు"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"డ్రైవింగ్‌లో ఉన్నప్పుడు, మీరు <xliff:g id="APP">%2$s</xliff:g> యాప్‌నకు <xliff:g id="COUNT">%1$d</xliff:g> అనుమతులను ఇచ్చారు"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{డ్రైవింగ్‌లో ఉన్నప్పుడు, మీరు <xliff:g id="APP_0">%1$s</xliff:g>, మరో # ఇతర యాప్‌నకు యాక్సెస్‌ను ఇచ్చారు}other{డ్రైవింగ్‌లో ఉన్నప్పుడు, మీరు <xliff:g id="APP_1">%1$s</xliff:g>, మరో # ఇతర యాప్‌లకు యాక్సెస్‌ను ఇచ్చారు}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"సెట్టింగ్‌లకు వెళ్లండి"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"గత కొన్ని నెలలుగా కొన్ని యాప్‌లు వినియోగంలో లేవు"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"అనుమతులు తీసివేసినవి"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"అనుమతులు తీసివేయబడ్డాయి"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"మీ ఫోన్ కాల్ లాగ్‌లను యాక్సెస్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ని అనుమతించాలా?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"ఫోన్‌ కాల్స్‌ చేయడానికి, మేనేజ్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ని అనుమతించాలా?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"మీ అత్యంత కీలకమైన గుర్తుల గురించి సెన్సార్ డేటాని యాక్సెస్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ని అనుమతించాలా?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"మీరు యాప్‌ను ఉపయోగించనప్పటికీ, ఈ యాప్ మీ కీలక ఆరోగ్య కొలమాన గుర్తుల సెన్సార్ డేటాను ఎప్పటికప్పుడు యాక్సెస్ చేయాలనుకుంటోంది. "<annotation id="link">"సెట్టింగ్‌లలో అనుమతించండి."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"మీరు యాప్‌ను ఉపయోగించనప్పటికీ, ఈ యాప్ మీ కీలక ఆరోగ్య కొలమాన గుర్తుల సెన్సార్ డేటాను ఎప్పటికప్పుడు యాక్సెస్ చేయాలనుకుంటోంది. ఈ మార్పు చేయడానికి, "<annotation id="link">"సెట్టింగ్‌లకు వెళ్లండి."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"మీ కీలక ఆరోగ్య కొలమాన గుర్తుల గురించి సెన్సార్ డేటాను యాక్సెస్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ను అనుమతించాలా?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"మీరు యాప్‌ను ఉపయోగించనప్పటికీ, ఈ యాప్ మీ కీలక ఆరోగ్య కొలమాన గుర్తుల సెన్సార్ డేటాను ఎప్పటికప్పుడు యాక్సెస్ చేయాలనుకోవచ్చు. "<annotation id="link">"సెట్టింగ్‌లలో అనుమతించండి."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; కోసం మీ కీలక ఆరోగ్య కొలమాన గుర్తులకు సంబంధించిన సెన్సార్ డేటాకు యాక్సెస్‌ను మార్చాలా?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"మీరు యాప్‌ను ఉపయోగించనప్పటికీ, ఈ యాప్ బాడీ సెన్సార్ డేటాను ఎప్పటికప్పుడు యాక్సెస్ చేయడాన్ని అనుమతించడానికి, "<annotation id="link">"సెట్టింగ్‌లకు వెళ్లండి."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"యాప్ ఉపయోగంలో ఉన్నప్పుడు బాడీ సెన్సార్ డేటాను యాక్సెస్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ను అనుమతించాలా?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"మీకు నోటిఫికేషన్‌లను పంపడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ను అనుమతించాలా?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"మీకు నోటిఫికేషన్‌లు పంపడాన్ని కొనసాగించడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ను అనుమతించాలా?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"నియంత్రణలో ఉన్న అనుమతులు"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"కెమెరా అనుమతిని తీసివేయండి"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"మైక్రోఫోన్ అనుమతిని తీసివేయండి"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"సర్వీస్‌ను మేనేజ్ చేయండి"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"అనుమతులను మేనేజ్ చేయగలరు"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"ఫోన్ కాల్ ద్వారా ఉపయోగించబడుతోంది"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"ఇటీవల ఫోన్ కాల్‌లో ఉపయోగించబడింది"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> ద్వారా ఉపయోగించబడుతోంది"</string>
diff --git a/PermissionController/res/values-th/strings.xml b/PermissionController/res/values-th/strings.xml
index 8fb5e863b..9d75dcc0d 100644
--- a/PermissionController/res/values-th/strings.xml
+++ b/PermissionController/res/values-th/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"ดูสิทธิ์ทั้งหมดของ \"<xliff:g id="APP">%1$s</xliff:g>\""</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"ดูแอปทั้งหมดที่มีสิทธิ์นี้"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"แสดงการใช้ไมโครโฟนของ Assistant"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"การตั้งค่าแอปที่ไม่ได้ใช้"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"นำสิทธิ์ออกหากไม่ได้ใช้งานแอป"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"นำสิทธิ์ออกและเพิ่มพื้นที่ว่าง"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"หากคุณไม่ได้ใช้งานแอปนาน 2-3 เดือน ระบบจะนำสิทธิ์ของแอปนี้ออกเพื่อปกป้องข้อมูลของคุณ"</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"หากไม่มีการใช้งานแอปนาน 2-3 เดือน ระบบจะปกป้องข้อมูลของคุณด้วยการนำสิทธิ์ต่อไปนี้ออก ได้แก่ <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"ระบบนำสิทธิ์ออกจากแอปที่คุณไม่ได้ใช้งานนาน 2-3 เดือนเพื่อปกป้องข้อมูลของคุณ"</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"คุณอนุญาตให้ <xliff:g id="APP">%1$s</xliff:g> เข้าถึง<xliff:g id="PERMISSION_1">%2$s</xliff:g>และ<xliff:g id="PERMISSION_2">%3$s</xliff:g>ในขณะขับรถ"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"คุณให้สิทธิ์ <xliff:g id="COUNT">%1$d</xliff:g> รายการแก่ <xliff:g id="APP">%2$s</xliff:g> ในขณะขับรถ"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{คุณอนุญาตให้ <xliff:g id="APP_0">%1$s</xliff:g> และแอปอื่นอีก # แอปเข้าถึงได้ในขณะขับรถ}other{คุณอนุญาตให้ <xliff:g id="APP_1">%1$s</xliff:g> และแอปอื่นอีก # แอปเข้าถึงได้ในขณะขับรถ}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"ไปที่การตั้งค่า"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"บางแอปไม่มีการใช้งานมา 2-3 เดือนแล้ว"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"นำสิทธิ์ออกแล้ว"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"นำสิทธิ์ออกแล้ว"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึงบันทึกการโทรในโทรศัพท์ไหม"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; โทรและจัดการการโทรไหม"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึงข้อมูลเซ็นเซอร์เกี่ยวกับสัญญาณชีพไหม"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"แอปนี้ต้องการเข้าถึงข้อมูลเซ็นเซอร์เกี่ยวกับสัญญาณชีพตลอดเวลา แม้ว่าคุณไม่ได้ใช้แอปก็ตาม "<annotation id="link">"อนุญาตในการตั้งค่า"</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"แอปนี้ต้องการเข้าถึงข้อมูลเซ็นเซอร์เกี่ยวกับสัญญาณชีพตลอดเวลาแม้ว่าคุณจะไม่ได้ใช้แอปอยู่ก็ตาม หากจะอนุญาตตามนี้ ให้"<annotation id="link">"ไปที่การตั้งค่า"</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึงข้อมูลเซ็นเซอร์เกี่ยวกับสัญญาณชีพไหม"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"แอปนี้อาจต้องการเข้าถึงข้อมูลเซ็นเซอร์เกี่ยวกับสัญญาณชีพตลอดเวลา แม้ว่าคุณไม่ได้ใช้แอปก็ตาม "<annotation id="link">"อนุญาตในการตั้งค่า"</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"เปลี่ยนแปลงสิทธิ์เข้าถึงข้อมูลเซ็นเซอร์เกี่ยวกับสัญญาณชีพสำหรับ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ไหม"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"หากต้องการให้แอปนี้เข้าถึงข้อมูลเซ็นเซอร์ร่างกายได้ทุกเมื่อ แม้ว่าคุณจะไม่ได้ใช้งานแอปอยู่ ให้"<annotation id="link">"ไปที่การตั้งค่า"</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึงข้อมูลเซ็นเซอร์ร่างกายได้ตลอดขณะใช้งานแอปไหม"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ส่งการแจ้งเตือนถึงคุณไหม"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ส่งการแจ้งเตือนถึงคุณต่อไปไหม"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"สิทธิ์ที่มีการควบคุม"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"นำสิทธิ์เข้าถึงกล้องออก"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"นำสิทธิ์เข้าถึงไมโครโฟนออก"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"จัดการบริการ"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"จัดการสิทธิ์"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"ใช้อยู่โดยการโทร"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"ใช้ล่าสุดโดยการโทร"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"ใช้อยู่โดย <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-tl/strings.xml b/PermissionController/res/values-tl/strings.xml
index beeb9a518..645a28a09 100644
--- a/PermissionController/res/values-tl/strings.xml
+++ b/PermissionController/res/values-tl/strings.xml
@@ -196,8 +196,11 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Tingnan ang lahat ng pahintulot ng <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Tingnan ang lahat ng app na may ganitong pahintulot"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Ipakita ang paggamit ng mikropono ng assistant"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Mga setting ng hindi ginagamit na app"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Alisin ang mga pahintulot kung hindi ginagamit ang app"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Alisin ang pahintulot, magbakante ng espasyo"</string>
+ <string name="unused_apps_label_v2" msgid="7058776770056517980">"I-pause ang aktibidad sa app kung hindi ginagamit"</string>
+ <string name="unused_apps_summary" msgid="8839466950318403115">"Alisin ang mga pahintulot, i-delete ang mga pansamantalang file, at ihinto ang mga notification"</string>
<string name="auto_revoke_summary" msgid="5867548789805911683">"Para maprotektahan ang iyong data, aalisin ang mga pahintulot para sa app na ito kapag ilang buwan nang hindi ginagamit ang app."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Para maprotektahan ang iyong data, kapag ilang buwan nang hindi ginagamit ang app, aalisin ang mga sumusunod na pahintulot: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Para protektahan ang iyong data, inalis na ang mga pahintulot sa mga app na ilang buwan mo nang hindi ginagamit."</string>
@@ -264,8 +267,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Habang nagmamaneho, binigyan mo ng access ang <xliff:g id="APP">%1$s</xliff:g> na <xliff:g id="PERMISSION_1">%2$s</xliff:g> at <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Habang nagmamaneho, nagbigay ka ng <xliff:g id="COUNT">%1$d</xliff:g> (na) pahintulot sa <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Habang nagmamaneho, binigyan mo ng access ang <xliff:g id="APP_0">%1$s</xliff:g> at # pang app}one{Habang nagmamaneho, binigyan mo ng access ang <xliff:g id="APP_1">%1$s</xliff:g> at # pang app}other{Habang nagmamaneho, binigyan mo ng access ang <xliff:g id="APP_1">%1$s</xliff:g> at # pang app}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Pumunta sa Mga Setting"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"May ilang app na ilang buwan nang hindi ginagamit"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Inalisan ng mga pahintulot"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Inalisan ng mga pahintulot"</string>
@@ -468,10 +470,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang iyong mga log ng tawag sa telepono?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na tumawag at mamahala ng mga tawag sa telepono?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang data ng sensor tungkol sa iyong mga vital sign?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Gustong palaging i-access ng app na ito ang data ng sensor tungkol sa iyong mga vital sign, kahit hindi mo ginagamit ang app. "<annotation id="link">"Payagan sa mga setting."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Gusto ng app na ito na palaging i-access ang data ng sensor tungkol sa iyong mga vital sign, kahit hindi mo ginagamit ang app. Para gawin ang pagbabagong ito, "<annotation id="link">"pumunta sa mga setting."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang data ng sensor tungkol sa iyong mga vital sign?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Posibleng palaging i-access ng app na ito ang data ng sensor tungkol sa mga vital sign mo, kahit hindi mo ginagamit ang app. "<annotation id="link">"Payagan sa mga setting."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Baguhin ang access sa data ng sensor tungkol sa iyong mga vital sign para sa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Para pahintulutan ang app na ito na i-access ang data ng sensor ng katawan sa lahat ng oras, kahit na hindi mo ginagamit ang app, "<annotation id="link">"pumunta sa mga setting."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Patuloy na pahintulutan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang data ng sensor ng katawan habang ginagamit ang app?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Payagan ang <xliff:g id="APP_NAME">%1$s</xliff:g> na padalhan ka ng mga notification?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Payagan ang <xliff:g id="APP_NAME">%1$s</xliff:g> na patuloy kang padalhan ng mga notification?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Kontroladong pahintulot"</string>
@@ -509,6 +511,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Alisin ang pahintulot sa camera"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Alisin ang pahintulot sa mikropono"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Pamahalaan ang serbisyo"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Pamahalaan ang mga pahintulot"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Ginagamit ng tawag sa telepono"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Kamakailang ginamit sa tawag sa telepono"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Ginagamit ng <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-tr/strings.xml b/PermissionController/res/values-tr/strings.xml
index cac44753e..a084ddf3b 100644
--- a/PermissionController/res/values-tr/strings.xml
+++ b/PermissionController/res/values-tr/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Tüm <xliff:g id="APP">%1$s</xliff:g> izinlerini göster"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Bu izne sahip tüm uygulamaları göster"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Yardımcı mikrofon kullanımını göster"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Kullanılmayan uygulama ayarları"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Uygulama kullanılmıyorsa izinleri kaldır"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"İzinleri kaldırıp yer aç"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Bu uygulama birkaç ay boyunca kullanılmazsa verilerinizi korumak için uygulamanın izinleri kaldırılır."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Uygulama birkaç ay boyunca kullanılmazsa şu izinler verilerinizi korumak için kaldırılacak: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Birkaç aydır kullanmadığınız uygulamaların izinleri verilerinizi korumak için kaldırıldı."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Sürüş sırasında <xliff:g id="APP">%1$s</xliff:g> uygulamasına <xliff:g id="PERMISSION_1">%2$s</xliff:g> ve <xliff:g id="PERMISSION_2">%3$s</xliff:g> erişim izni verdiniz"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Sürüş sırasında <xliff:g id="APP">%2$s</xliff:g> uygulamasına <xliff:g id="COUNT">%1$d</xliff:g> izin verdiniz"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Sürüş sırasında <xliff:g id="APP_0">%1$s</xliff:g> uygulamasına ve # uygulamaya daha erişim izni verdiniz}other{Sürüş sırasında <xliff:g id="APP_1">%1$s</xliff:g> uygulamasına ve # uygulamaya daha erişim izni verdiniz}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Ayarlar\'a git"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Bazı uygulamalar birkaç aydır kullanılmadı"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"İzinleri kaldırılmış"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"İzinleri kaldırılmış"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının telefon arama kayıtlarınıza erişmesine izin verilsin mi?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının telefon etmesine ve aramaları yönetmesine izin verilsin mi?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının hayati belirtilerinizle ilgili sensör verilerine erişmesine izin verilsin mi?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Bu uygulama, kullanmadığınız sırada bile hayati belirtilerinizle ilgili sensör verilerine sürekli olarak erişmek istiyor. "<annotation id="link">"Ayarlar\'da izin verin."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Bu uygulama, kullanmadığınız sırada bile hayati belirtilerinizle ilgili sensör verilerine sürekli olarak erişmek istiyor. Bu değişikliği yapmak için "<annotation id="link">"ayarlara gidin."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının hayati belirtilerinizle ilgili sensör verilerine erişmesine izin verilsin mi?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Bu uygulama, kullanmadığınız sırada bile hayati belirtilerinizle ilgili sensör verilerine sürekli olarak erişmek isteyebilir. "<annotation id="link">"Ayarlar\'da izin verin."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının hayati belirtilerinizle ilgili sensör verilerine erişimi değiştirilsin mi?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Bu uygulamanın, kullanmadığınız sırada bile vücut sensörü verilerine sürekli olarak erişmesine izin vermek için "<annotation id="link">"ayarlara gidin."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının kullanımdayken vücut sensörü verilerine erişme izni sürdürülsün mü?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının size bildirim göndermesine izin verilsin mi?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının size bildirim göndermeye devam etmesine izin verilsin mi?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Kontrol edilen izinler"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Kamera iznini kaldır"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Mikrofon iznini kaldır"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Hizmeti yönet"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"İzinleri yönetin"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Telefon aramasında kullanılıyor"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Yakın zamanda telefon aramasında kullanıldı"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> tarafından kullanılıyor"</string>
diff --git a/PermissionController/res/values-uk/strings.xml b/PermissionController/res/values-uk/strings.xml
index 8f6965320..388f7dedd 100644
--- a/PermissionController/res/values-uk/strings.xml
+++ b/PermissionController/res/values-uk/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Переглянути всі дозволи додатка <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Переглянути всі додатки з цим дозволом"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Показати статус мікрофона Асистента"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Налаштування невикористовуваних додатків"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Відкликати дозволи, якщо додаток не використовується"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Вилучати дозволи й звільняти місце"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Щоб захистити ваші дані, дозволи для цього додатка буде автоматично скасовано, якщо ви не будете користуватися ним кілька місяців."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Якщо додаток не використовується впродовж кількох місяців, для захисту ваших даних буде скасовано такі дозволи: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Щоб захистити ваші дані, було скасовано дозволи додатків, які не використовувалися впродовж кількох місяців."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Під час руху ви надали додатку <xliff:g id="APP">%1$s</xliff:g> дозвіл на доступ до таких об’єктів: <xliff:g id="PERMISSION_1">%2$s</xliff:g> і <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Під час руху ви надали додатку <xliff:g id="APP">%2$s</xliff:g> стільки дозволів: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Під час руху ви надали дозвіл на доступ додатку <xliff:g id="APP_0">%1$s</xliff:g> і ще одному додатку}one{Під час руху ви надали дозвіл на доступ додатку <xliff:g id="APP_1">%1$s</xliff:g> і ще # додатку}few{Під час руху ви надали дозвіл на доступ додатку <xliff:g id="APP_1">%1$s</xliff:g> і ще # додаткам}many{Під час руху ви надали дозвіл на доступ додатку <xliff:g id="APP_1">%1$s</xliff:g> і ще # додаткам}other{Під час руху ви надали дозвіл на доступ додатку <xliff:g id="APP_1">%1$s</xliff:g> і ще # додатка}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Перейти до налаштувань"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Деякі додатки не використовувалися кілька місяців"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Скасовані дозволи"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Дозволи скасовано"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ до журналів викликів телефона?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; здійснювати телефонні дзвінки та керувати ними?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Надати додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ до життєвих показників із датчиків?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Цей додаток хоче постійно отримувати дані життєвих показників із датчиків, навіть коли ви не використовуєте його. "<annotation id="link">"Надайте дозвіл у налаштуваннях."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Цей додаток хоче постійно отримувати дані життєвих показників від датчиків, навіть коли ви не використовуєте його. Щоб внести зміни, "<annotation id="link">"перейдіть у налаштування"</annotation>"."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ до життєвих показників із датчиків?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Цей додаток може постійно отримувати дані життєвих показників із датчиків, навіть коли ви не використовуєте його. "<annotation id="link">"Надайте дозвіл у налаштуваннях."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Змінити доступ до життєвих показників із датчиків для додатка &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Щоб надати додатку постійний доступ до показників датчиків на тілі, навіть коли він не використовується, "<annotation id="link">"перейдіть у налаштування"</annotation>"."</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Надавати й надалі додатку <xliff:g id="APP_NAME">%1$s</xliff:g> доступ до показників датчиків на тілі, коли він використовується?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; надсилати вам сповіщення?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; і надалі надсилати вам сповіщення?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Керовані дозволи"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Вилучити дозвіл на доступ до камери"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Вилучити дозвіл на доступ до мікрофона"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Керувати сервісом"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Керувати дозволами"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Використовується в телефонному дзвінку"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Нещодавно використано в телефонному дзвінку"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Використовується в додатку <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-ur/strings.xml b/PermissionController/res/values-ur/strings.xml
index d5af70dd0..4c6a7f65e 100644
--- a/PermissionController/res/values-ur/strings.xml
+++ b/PermissionController/res/values-ur/strings.xml
@@ -196,8 +196,14 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"<xliff:g id="APP">%1$s</xliff:g> کی سبھی اجازتیں دیکھیں"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"اس اجازت والی سبھی ایپس دیکھیں"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"اسسٹنٹ مائیکروفون کا استعمال دکھائیں"</string>
+ <!-- no translation found for unused_apps_category_title (2988455616845243901) -->
+ <skip />
<string name="auto_revoke_label" msgid="5068393642936571656">"ایپ کے استعمال نہ ہونے پر اجازتیں ہٹائیں"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"اجازتوں کو ہٹائیں اور جگہ خالی کریں"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"آپ کے ڈیٹا کی حفاظت کے لیے، اگر ایپ کو کچھ مہینوں تک استعمال نہیں کیا گیا تو اس ایپ کے لیے اجازتیں ہٹا دی جائیں گی۔"</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"آپ کے ڈیٹا کی حفاظت کے لیے، اگر ایپ کو کچھ مہینوں تک استعمال نہیں کیا گيا تو درج ذیل اجازتیں ہٹا دی جائیں گی: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"آپ کے ڈیٹا کی حفاظت کے لیے، اجازتوں کو ان ایپس سے ہٹا دیا گیا ہے جنہیں آپ نے کچھ مہینوں سے استعمال نہیں کیا ہے۔"</string>
@@ -264,8 +270,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"ڈرائیونگ کے دوران، آپ نے <xliff:g id="APP">%1$s</xliff:g> کو <xliff:g id="PERMISSION_1">%2$s</xliff:g> اور <xliff:g id="PERMISSION_2">%3$s</xliff:g> تک رسائی دی"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"ڈرائیونگ کے دوران، آپ نے <xliff:g id="APP">%2$s</xliff:g> کو <xliff:g id="COUNT">%1$d</xliff:g> اجازتیں دیں"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{ڈرائیونگ کے دوران، آپ نے <xliff:g id="APP_0">%1$s</xliff:g> اور # دیگر ایپ تک رسائی دی}other{ڈرائیونگ کے دوران، آپ نے <xliff:g id="APP_1">%1$s</xliff:g> اور # دیگر ایپس تک رسائی دی}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"ترتیبات پر جائیں"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"کچھ ایپس کا استعمال کچھ مہینوں سے نہیں کیا گیا ہے"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"ہٹائی گئی اجازتیں"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"اجازتیں ہٹا دی گئیں"</string>
@@ -468,10 +473,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"‏‎&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;‎ کو آپ کے فون کال لاگز تک رسائی کی اجازت دیں؟"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"‏&lt;/b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو فون کالز کرنے اور ان کا نظم کرنے کی اجازت دیں؟"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو آپ کے اہم اشاروں کے متعلق سینسر ڈیٹا تک رسائی کی اجازت دیں؟"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"یہ ایپ ہر وقت آپ کے اہم اشاروں کے بارے میں سینسر ڈیٹا تک رسائی حاصل کرنا چاہتی ہے، اگرچہ جب آپ ایپ استعمال نہ کر رہے ہوں۔ "<annotation id="link">"ترتیبات میں اجازت دیں۔"</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"آپ کے ایپ کا استعمال نہ کرنے کے باوجود یہ ایپ ہر وقت آپ کے اہم علامتوں کے متعلق سینسر ڈیٹا تک رسائی حاصل کرنا چاہتی ہے۔ یہ تبدیلی کرنے کے لیے "<annotation id="link">"ترتیبات پر جائیں۔"</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&amp;gt کو آپ کے اہم اشاروں کے متعلق سینسر ڈیٹا تک رسائی کی اجازت دیں؟"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"ممکن ہے یہ ایپ ہر وقت آپ کے اہم اشاروں کے بارے میں سینسر ڈیٹا تک رسائی حاصل کرنا چاہے، اگرچہ جب آپ ایپ استعمال نہ کر رہے ہوں۔ "<annotation id="link">"ترتیبات میں اجازت دیں۔"</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;? کے لیے اپنے اہم اشاروں کے بارے میں سینسر ڈیٹا تک رسائی کو تبدیل کریں؟"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"آپ کے ایپ کا استعمال نہ کرنے کے باوجود اس ایپ کو ہر وقت باڈی سینسر ڈیٹا تک رسائی کی اجازت دینے کے لیے "<annotation id="link">"ترتیبات پر جائیں۔"</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"‏ایپ کے استعمال میں ہونے کے دوران ‎&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;‎ کو باڈی سینسر ڈیٹا تک رسائی کی اجازت دینا جاری رکھیں؟"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>‏&lt;/b&gt; کو آپ کو اطلاعات بھیجنے کی اجازت دیں؟"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>‏&lt;/b&gt; کو آپ کو اطلاعات بھیجنا جاری رکھنے کی اجازت دیں؟"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"کنٹرول کی گئی اجازتیں"</string>
@@ -509,6 +514,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"کیمرے کی اجازت کو ہٹا دیا گیا"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"مائیکروفون کی اجازت کو ہٹا دیا گیا"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"سروس کا نظم کریں"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"اجازتوں کا نظم کریں"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"فون کال کے ذریعے استعمال کیا جا رہا ہے"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"فون کال میں حال ہی میں استعمال کیا گیا"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے ذریعے استعمال کیا جا رہا ہے"</string>
diff --git a/PermissionController/res/values-uz/strings.xml b/PermissionController/res/values-uz/strings.xml
index 25063aaca..a8516de2a 100644
--- a/PermissionController/res/values-uz/strings.xml
+++ b/PermissionController/res/values-uz/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"<xliff:g id="APP">%1$s</xliff:g> uchun berilgan barcha ruxsatlar"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Bu ruxsatga ega barcha ilovalar"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Assistent uchun mikrofondan foydalanishni koʻrsatish"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Ishlatilmagan ilova sozlamalari"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Ishlatilmayotgan ilovalardan ruxsatlarni olib tashlash"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Ruxsatlarni olib tashlash va joy ochish"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Xavfsizlik yuzasidan, bir necha oydan beri ishlatilmagan ilovalardan ruxsatlar olib tashlanadi"</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Agar bu ilova bir necha oy ishlatilmasa, quyidagi ruxsatlar olib tashlanadi: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Xavfsizlik yuzasidan, bir necha oydan beri ishlatilmagan ilovalardan ruxsatlar olib tashlanadi"</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Haydash vaqtida <xliff:g id="APP">%1$s</xliff:g> ilovasiga <xliff:g id="PERMISSION_1">%2$s</xliff:g> va <xliff:g id="PERMISSION_2">%3$s</xliff:g> ruxsatlarini bergansiz"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Haydash vaqtida <xliff:g id="APP">%2$s</xliff:g> ilovasiga <xliff:g id="COUNT">%1$d</xliff:g> ta ruxsat bergansiz"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Haydash vaqtida <xliff:g id="APP_0">%1$s</xliff:g> va yana # ta ilovaga ruxsat bergansiz}other{Haydash vaqtida <xliff:g id="APP_1">%1$s</xliff:g> va yana # ta ilovaga ruxsat bergansiz}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Sozlamalarni ochish"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Ayrim ilovalar bir necha oydan beri ishlatilmagan."</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Olib tashlangan ruxsatlar"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Ruxsatlar olib tashlandi"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun telefoningizdagi chaqiruvlar tarixiga kirish ruxsati berilsinmi?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun telefon chaqiruvlarini amalga oshirish va boshqarish ruxsati berilsinmi?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun organizm holati haqidagi sezgichlar axborotlariga ruxsat berilsinmi?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Bu ilova doimo, hatto ishlatilmaganida ham organizm holati haqidagi sensor axborotlaridan foydalanmoqchi. "<annotation id="link">"Sozlamalar orqali ruxsat bering."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Bu ilova organizm holati haqidagi sensor maʼlumotlaringizdan doimiy foydalanishga ruxsat olmoqchi. Bu ruxsatni berish uchun "<annotation id="link">"sozlamalarni oching."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun organizm holati haqidagi sensor axborotlariga ruxsat berilsinmi?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Bu ilova doimo, hatto ishlatilmaganida ham organizm holati haqidagi sensor axborotlaridan foydalanmoqchi. "<annotation id="link">"Sozlamalar orqali ruxsat bering."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun organizm holati haqidagi sensor axborotlariga ruxsat oʻzgartirilsinmi?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Bu ilovaga tanadagi sensor maʼlumotlaridan foydalanishga (hatto ilova yopiqligida ham) doimiy ruxsat berish uchun "<annotation id="link">"sozlamalarni oching."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ilovasi tanadagi sensor maʼlumotlaridan foydalanishiga ruxsat berilaversinmi?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ilovasiga sizga bildirishnomalar yuborishi uchun ruxsat berilsinmi?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ilovasining sizga bildirishnomalar yuborishda davom etishiga ruxsat berasizmi?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Boshqariluvchi ruxsatlar"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Kameraga ruxsatni olib tashlash"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Mikrofonga ruxsatni olib tashlash"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Xizmatni boshqarish"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Ruxsatlarni boshqarish"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Telefon chaqiruvi ishlatmoqda"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Yaqinda telefon chaqiruvi ishlatgan"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> ishlatmoqda"</string>
diff --git a/PermissionController/res/values-vi/strings.xml b/PermissionController/res/values-vi/strings.xml
index 5e002d5f8..67b0fd84d 100644
--- a/PermissionController/res/values-vi/strings.xml
+++ b/PermissionController/res/values-vi/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Xem tất cả các quyền của <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Xem tất cả ứng dụng có quyền này"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Hiển thị việc sử dụng micrô của Trợ lý"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Các chế độ cài đặt ứng dụng chưa dùng"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Thu hồi quyền nếu không dùng ứng dụng"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Thu hồi quyền và giải phóng dung lượng"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Để bảo vệ dữ liệu của bạn, các quyền cấp cho ứng dụng này sẽ bị thu hồi nếu bạn không dùng ứng dụng trong vài tháng."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Để bảo vệ dữ liệu của bạn, nếu bạn không dùng ứng dụng này trong vài tháng thì các quyền sau đây sẽ bị thu hồi: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Để bảo vệ dữ liệu của bạn, quản trị viên CNTT đã thu hồi các quyền đối với những ứng dụng bạn không dùng trong vài tháng."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Trong khi lái xe, bạn đã cấp cho <xliff:g id="APP">%1$s</xliff:g> quyền truy cập vào <xliff:g id="PERMISSION_1">%2$s</xliff:g> và <xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Trong khi lái xe, bạn đã cấp <xliff:g id="COUNT">%1$d</xliff:g> quyền cho <xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Trong khi lái xe, bạn đã cấp quyền truy cập cho <xliff:g id="APP_0">%1$s</xliff:g> và # ứng dụng khác}other{Trong khi lái xe, bạn đã cấp quyền truy cập cho <xliff:g id="APP_1">%1$s</xliff:g> và # ứng dụng khác}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Chuyển đến phần Cài đặt"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Bạn không dùng một số ứng dụng trong vài tháng qua"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Các quyền bị xóa"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Các quyền đã thu hồi"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; truy cập vào nhật ký cuộc gọi điện thoại của bạn?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; thực hiện và quản lý cuộc gọi điện thoại?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; truy cập vào dữ liệu cảm biến về các dấu hiệu sinh tồn của bạn?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Ứng dụng này muốn truy cập dữ liệu cảm biến về dấu hiệu sinh tồn của bạn mọi lúc, ngay cả khi bạn không dùng ứng dụng. "<annotation id="link">"Cho phép trong phần cài đặt."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Ứng dụng này muốn truy cập vào dữ liệu cảm biến về các dấu hiệu liên quan đến chỉ số sức khoẻ bất cứ lúc nào, ngay cả khi bạn không dùng ứng dụng. Để thay đổi, hãy "<annotation id="link">"chuyển đến phần cài đặt."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; truy cập vào dữ liệu cảm biến về các dấu hiệu sinh tồn của bạn?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Ứng dụng này muốn truy cập dữ liệu cảm biến về dấu hiệu sinh tồn của bạn mọi lúc, ngay cả khi bạn không dùng ứng dụng. "<annotation id="link">"Cho phép trong phần cài đặt."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Thay đổi quyền truy cập của &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vào dữ liệu cảm biến về các dấu hiệu sinh tồn của bạn?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Để cho phép ứng dụng này truy cập vào dữ liệu cảm biến cơ thể bất cứ lúc nào, ngay cả khi bạn không dùng ứng dụng, hãy "<annotation id="link">"chuyển đến phần cài đặt."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Luôn cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; truy cập vào dữ liệu cảm biến cơ thể trong khi đang dùng ứng dụng?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; gửi thông báo cho bạn?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tiếp tục gửi thông báo cho bạn?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Các quyền bị kiểm soát"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Thu hồi quyền sử dụng máy ảnh"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Thu hồi quyền sử dụng micrô"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Quản lý dịch vụ"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Quản lý quyền"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Đang được dùng cho một cuộc gọi điện thoại"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Đã dùng gần đây trong một cuộc gọi điện thoại"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang dùng"</string>
diff --git a/PermissionController/res/values-zh-rCN/strings.xml b/PermissionController/res/values-zh-rCN/strings.xml
index 09725955b..e1b9e0e47 100644
--- a/PermissionController/res/values-zh-rCN/strings.xml
+++ b/PermissionController/res/values-zh-rCN/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"查看“<xliff:g id="APP">%1$s</xliff:g>”的所有权限"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"查看具有此权限的所有应用"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"显示 Google 助理麦克风使用情况"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"关于未使用应用的设置"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"如果未使用此应用,则移除相关权限"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"撤消权限并释放空间"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"为了保护您的数据,如果您连续几个月未使用此应用,系统会移除它的权限。"</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"为了保护您的数据,如果您连续几个月未使用此应用,系统会移除其以下权限:<xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"为了保护您的数据,对于您连续几个月未使用过的应用,系统已将其权限移除。"</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"您在行车期间向“<xliff:g id="APP">%1$s</xliff:g>”授予了<xliff:g id="PERMISSION_1">%2$s</xliff:g>和<xliff:g id="PERMISSION_2">%3$s</xliff:g>权限"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"您在行车期间向“<xliff:g id="APP">%2$s</xliff:g>”授予了 <xliff:g id="COUNT">%1$d</xliff:g> 项权限"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{您在行车期间向“<xliff:g id="APP_0">%1$s</xliff:g>”和另外 # 个应用授予了权限}other{您在行车期间向“<xliff:g id="APP_1">%1$s</xliff:g>”和另外 # 个应用授予了权限}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"转到“设置”"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"一些应用已连续几个月未使用过"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"已移除权限的应用"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"已移除权限的应用"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;访问您的手机通话记录吗?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"允许“&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;”拨打电话和管理通话吗?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;访问与您的生命体征相关的传感器数据吗?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"此应用想要随时访问与您的生命体征相关的传感器数据(即使在您未使用此应用时)。"<annotation id="link">"您可以在“设置”中允许。"</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"此应用希望随时都能访问与您的生命体征相关的传感器数据(即使在您未使用此应用时)。如要进行这种权限更改,请"<annotation id="link">"前往设置页面"</annotation>"。"</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"要允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;访问与您的生命体征相关的传感器数据吗?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"此应用可能想要随时访问与您的生命体征相关的传感器数据(即使在您未使用此应用时)。"<annotation id="link">"您可以在“设置”中允许。"</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"要更改&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;对与您的生命体征相关的传感器数据的访问权限吗?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"如要允许此应用始终可以访问身体传感器数据(即使在您未使用此应用时),请"<annotation id="link">"前往设置"</annotation>"。"</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"始终允许“<xliff:g id="APP_NAME">%1$s</xliff:g>”在使用中时访问身体传感器数据?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"允许 &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; 向您发送通知吗?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"允许 &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; 继续向您发送通知吗?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"受控权限"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"移除相机权限"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"移除麦克风权限"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"管理服务"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"管理权限"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"通话正在使用"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"最近在通话中使用过"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正在使用"</string>
diff --git a/PermissionController/res/values-zh-rHK/strings.xml b/PermissionController/res/values-zh-rHK/strings.xml
index 9facf1fe2..f5398d0d0 100644
--- a/PermissionController/res/values-zh-rHK/strings.xml
+++ b/PermissionController/res/values-zh-rHK/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"查看「<xliff:g id="APP">%1$s</xliff:g>」的所有權限"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"查看擁有此權限的所有應用程式"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"顯示「Google 助理」麥克風使用情況"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"未使用的應用程式設定"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"如不使用應用程式,即移除權限"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"移除權限並騰出空間"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"為保護您的資料,系統已移除您在過去幾個月未曾使用的應用程式的權限。"</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"為保護您的資料,如果應用程式在過去幾個月未曾使用,系統將會移除以下權限:<xliff:g id="PERMS">%1$s</xliff:g>。"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"為保護您的資料,系統已移除您在過去幾個月未曾使用的應用程式的權限。"</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"您在駕駛時已將<xliff:g id="PERMISSION_1">%2$s</xliff:g>和<xliff:g id="PERMISSION_2">%3$s</xliff:g>的存取權授予「<xliff:g id="APP">%1$s</xliff:g>」"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"您在駕駛時已將 <xliff:g id="COUNT">%1$d</xliff:g> 項權限授予「<xliff:g id="APP">%2$s</xliff:g>」"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{您在駕駛時已將存取權授予「<xliff:g id="APP_0">%1$s</xliff:g>」和另外 # 個應用程式}other{您在駕駛時已將存取權授予「<xliff:g id="APP_1">%1$s</xliff:g>」和另外 # 個應用程式}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"前往「設定」"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"部分應用程式在過去幾個月都沒有用過。"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"已移除權限的應用程式"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"權限已移除的應用程式"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取您的手機通話記錄嗎?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;撥打電話和管理通話嗎?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取與您身體機能相關的感應器資料嗎?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"此應用程式要求持續存取與您生命體徵相關的感應器資料 (即使在您沒有使用此應用程式時)。"<annotation id="link">"請在設定中允許權限。"</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"此應用程式要求持續存取與您生命體徵相關的感應器資料 (即使在您沒有使用此應用程式時)。如要變更,請"<annotation id="link">"前往設定。"</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」存取與您生命體徵相關的感應器資料嗎?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"此應用程式要求持續存取與您生命體徵相關的感應器資料 (即使在您沒有使用此應用程式時)。"<annotation id="link">"請在設定中允許權限。"</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"要變更「<xliff:g id="APP_NAME">%1$s</xliff:g>」對與您生命體徵相關的感應器資料的存取權嗎?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"如要讓此應用程隨時存取人體感應器資料 (即使在您沒有使用此應用程式時),請"<annotation id="link">"前往設定"</annotation>"。"</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"要讓「<xliff:g id="APP_NAME">%1$s</xliff:g>」應用程式&lt;b&gt;&lt;/b&gt;在使用時存取人體感應器資料嗎?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"要允許 &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; 傳送通知給您嗎?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"要允許 &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; 繼續傳送通知給您嗎?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"由管理員控制的權限"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"移除相機權限"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"移除麥克風權限"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"管理服務"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"管理權限"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"手機通話正在使用此權限"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"手機通話最近使用過此權限"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在使用此權限"</string>
diff --git a/PermissionController/res/values-zh-rTW/strings.xml b/PermissionController/res/values-zh-rTW/strings.xml
index 5ff5d5e93..2a18645b1 100644
--- a/PermissionController/res/values-zh-rTW/strings.xml
+++ b/PermissionController/res/values-zh-rTW/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"查看「<xliff:g id="APP">%1$s</xliff:g>」的所有權限"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"查看具備此權限的所有應用程式"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"顯示 Google 助理的麥克風使用狀況"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"未使用的應用程式設定"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"如果應用程式未使用,讓系統移除相關權限"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"移除權限並釋出空間"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"為了保護你的資料,如果你連續幾個月都未使用這個應用程式,系統會移除其權限。"</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"為了保護你的資料,如果應用程式已有數個月未使用,系統將移除以下權限:<xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"為了保護你的資料,針對數個月未使用的應用程式,系統已移除相關權限。"</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"你已在開車時將<xliff:g id="PERMISSION_1">%2$s</xliff:g>和<xliff:g id="PERMISSION_2">%3$s</xliff:g>的存取權授予「<xliff:g id="APP">%1$s</xliff:g>」"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"你已在開車時將 <xliff:g id="COUNT">%1$d</xliff:g> 項權限授予「<xliff:g id="APP">%2$s</xliff:g>」"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{你已在開車時將存取權授予「<xliff:g id="APP_0">%1$s</xliff:g>」和另外 # 個應用程式}other{你已在開車時將存取權授予「<xliff:g id="APP_1">%1$s</xliff:g>」和另外 # 個應用程式}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"前往「設定」"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"某些應用程式已有數個月未使用"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"已移除權限的應用程式類別"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"已移除權限的應用程式"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取你的通話記錄嗎?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」撥打電話及管理通話嗎?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」存取與你生命徵象相關的感應器資料嗎?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"這個應用程式想要隨時存取與你生命徵象相關的感應器資料 (即使你當下並未使用該應用程式)。如要授予權限,請"<annotation id="link">"前往「設定」"</annotation>"。"</string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"這個應用程式想隨時存取與你生命徵象相關的感應器資料 (即使你當下並未使用該應用程式)。如要變更,請"<annotation id="link">"前往設定"</annotation>"。"</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取與你生命徵象相關的感應器資料嗎?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"這個應用程式可能想要隨時存取與你生命徵象相關的感應器資料 (即使你當下並未使用該應用程式)。如要授予權限,請"<annotation id="link">"前往「設定」"</annotation>"。"</string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;要求存取與你生命徵象相關的人體感應器資料,要變更這個應用程式的權限嗎?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"如要讓這個應用程能隨時存取人體感應器資料 (即使你當下並未使用該應用程式),請"<annotation id="link">"前往設定"</annotation>"。"</string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;應用程式在使用期間存取人體感應器資料嗎?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;傳送通知嗎?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;繼續傳送通知嗎?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"由管理員控管的權限"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"移除相機權限"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"移除麥克風權限"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"管理服務"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"管理權限"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"手機通話正在使用這項權限"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"手機通話最近用過這項權限"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在使用這項權限"</string>
diff --git a/PermissionController/res/values-zu/strings.xml b/PermissionController/res/values-zu/strings.xml
index 340097d9a..49cc9b1b9 100644
--- a/PermissionController/res/values-zu/strings.xml
+++ b/PermissionController/res/values-zu/strings.xml
@@ -196,8 +196,13 @@
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Bona zonke izimvume ze-<xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Bona zonke izinhlelo zokusebenza ngale mvume"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Bonisa ukusetshenziswa kwe-microphone kamsizi"</string>
+ <string name="unused_apps_category_title" msgid="2988455616845243901">"Amasethingi we-app engasetshenziswanga"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Susa izimvume uma uhlelo lokusebenza lungasetshenziswa"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Susa izimvume uphinde ukhulule isikhala"</string>
+ <!-- no translation found for unused_apps_label_v2 (7058776770056517980) -->
+ <skip />
+ <!-- no translation found for unused_apps_summary (8839466950318403115) -->
+ <skip />
<string name="auto_revoke_summary" msgid="5867548789805911683">"Ukuze kuvikelwe idatha yakho, izimvume zalolu hlelo lokusebenza zizosuswa uma uhlelo lokusebenza lungasetshenziswa izinyanga ezimbalwa."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Ukuze kuvikelwe idatha yakho, uma uhlelo lokusebenza lungasetshenzisiwe, izimvume ezilandelayo zizosuswa: <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Ukuze kuvikelwe idatha yakho, izimvume zisusiwe kusukela kuzinhlelo zokusebenza ongazange uzisebenzise ezinyangeni ezimbalwa."</string>
@@ -264,8 +269,7 @@
<string name="post_drive_permission_decision_reminder_summary_1_app_2_permissions" msgid="671791184670801301">"Ngenkathi ushayela, unikeze i-<xliff:g id="APP">%1$s</xliff:g> ukufinyelela ku-<xliff:g id="PERMISSION_1">%2$s</xliff:g> ne-<xliff:g id="PERMISSION_2">%3$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_1_app_multi_permission" msgid="4080701771111456927">"Ngenkathi ushayela, unikeze izimvume ezingu-<xliff:g id="COUNT">%1$d</xliff:g> ku-<xliff:g id="APP">%2$s</xliff:g>"</string>
<string name="post_drive_permission_decision_reminder_summary_multi_apps" msgid="5253882771252863902">"{count,plural, =1{Ngenkathi ushayela, unikeze i-<xliff:g id="APP_0">%1$s</xliff:g> namanye ama-app angu-# ukufinyelela}one{Ngenkathi ushayela, unikeze i-<xliff:g id="APP_1">%1$s</xliff:g> namanye ama-app angu-# ukufinyelela}other{Ngenkathi ushayela, unikeze i-<xliff:g id="APP_1">%1$s</xliff:g> namanye ama-app angu-# ukufinyelela}}"</string>
- <!-- no translation found for go_to_settings (1053735612211228335) -->
- <skip />
+ <string name="go_to_settings" msgid="1053735612211228335">"Iya Kumasethingi"</string>
<string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"Ezinye izinhlelo zokusebenza azisetshenziswanga ezinyangeni ezimbalwa"</string>
<string name="permissions_removed_category_title" msgid="1064754271178447643">"Izimvume ezisusiwe"</string>
<string name="permission_removed_page_title" msgid="2627436155091001209">"Izimvume zisusiwe"</string>
@@ -468,10 +472,10 @@
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukufinyelela kurekhodi lakho lamakholi wefoni?"</string>
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi yenze iphinde iphathe amakholi efoni?"</string>
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi ifinyelele kudatha yenzwa emayelana nezimpawu zakho ezibalulekile?"</string>
- <string name="permgroupupgraderequestdetail_sensors" msgid="5239219356063824373">"Le app ifuna ukufinyelela idatha yenzwa emayelana nezimpawu zakho ezibalulekile ngaso sonke isikhathi, nanoma ungasebenzisi i-app. "<annotation id="link">"Vumela kumasethingi."</annotation></string>
+ <string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Le app ifuna ukufinyelela kudatha yenzwa emayelana nezimpawu zakho ezibalulekile ngaso sonke isikhathi, ngisho noma ungasebenzisi i-app. "<annotation id="link">"iya kumasethingi."</annotation></string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi ifinyelele kudatha yenzwa emayelana nezimpawu zakho ezibalulekile?"</string>
- <string name="permgroupbackgroundrequestdetail_sensors" msgid="4853242818919117016">"Le app ingase ifune ukufinyelela kudatha yenzwa emayelana nezimpawu zakho ezibalulekile ngaso sonke isikhathi, ngisho nalapho ungasebenzisi i-app. "<annotation id="link">"Vumela kumasethingi."</annotation></string>
- <string name="permgroupupgraderequest_sensors" msgid="3346259833500506859">"Shintsha ukufinyelela kudatha yenzwa mayelana ne-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7649389834182449783">"Ukuze uvumele le app ukuba ifinyelele idatha yenzwa yomzimba ngaso sonke isikhathi, nanoma ungasebenzisi i-app, "<annotation id="link">"iya kumasethingi."</annotation></string>
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Qhubeka uvumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuba ifinyelele inzwa yedatha yomzimba kuyilapho i-app isebenza?"</string>
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi ikuthumele izaziso?"</string>
<string name="permgrouprequestcontinue_notifications" msgid="3895098107355024027">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi iqhubeke nokukuthumela izaziso?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Izimvume ezilawuliwe"</string>
@@ -509,6 +513,7 @@
<string name="remove_camera_qs" msgid="8209716677879809162">"Susa imvume yekhamera"</string>
<string name="remove_microphone_qs" msgid="2893536836641560183">"Susa imvume yemakrofoni"</string>
<string name="manage_service_qs" msgid="7862555549364153805">"Phatha isevisi"</string>
+ <string name="manage_permissions_qs" msgid="3780541819763475434">"Phatha izimvume"</string>
<string name="active_call_usage_qs" msgid="8559974395932523391">"Bekusetshenziswa yikholi yefoni"</string>
<string name="recent_call_usage_qs" msgid="743044899599410935">"Kusetshenziswa kamuva kwikholi yefoni"</string>
<string name="active_app_usage_qs" msgid="4063912870936464727">"Kusetshenziswa yi-<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values/strings.xml b/PermissionController/res/values/strings.xml
index 850b4ecb7..69de42eb2 100644
--- a/PermissionController/res/values/strings.xml
+++ b/PermissionController/res/values/strings.xml
@@ -606,12 +606,21 @@
<!-- Label for the assistant mic display switch [CHAR LIMIT=60] -->
<string name="assistant_mic_label">Show assistant microphone usage</string>
+ <!-- Category title for unused apps on T+ devices [CHAR LIMIT=40] -->
+ <string name="unused_apps_category_title">Unused app settings</string>
+
<!-- Label for the auto revoke switch on pre-S devices [CHAR LIMIT=60] -->
<string name="auto_revoke_label">Remove permissions if app isn\u2019t used</string>
- <!-- Label for the hibernation / auto revoke switch on S+ devices [CHAR LIMIT=40] -->
+ <!-- Label for the hibernation / auto revoke switch on S devices [CHAR LIMIT=40] -->
<string name="unused_apps_label">Remove permissions and free up space</string>
+ <!-- Label for the hibernation / auto revoke switch on T+ devices [CHAR LIMIT=40] -->
+ <string name="unused_apps_label_v2">Pause app activity if unused</string>
+
+ <!-- Hibernation switch preference summary which describes what the toggle does on T+ devices [CHAR LIMIT=NONE] -->
+ <string name="unused_apps_summary">Remove permissions, delete temporary files, and stop notifications</string>
+
<!-- Summary for stating that permissions will be removed [CHAR LIMIT=none] -->
<string name="auto_revoke_summary">To protect your data, permissions for this app will be removed if the app is unused for a few months.</string>
@@ -1428,7 +1437,7 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access sensor data about your vital signs?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the body sensors while app is in foreground and background. Try to keep the link annotation at the end of the string [CHAR LIMIT=NONE] -->
- <string name="permgroupupgraderequestdetail_sensors">This app wants to access sensor data about your vital signs all the time, even when you\u2019re not using the app. To make this change, <annotation id="link">go to settings</annotation> or keep access for only while the app is in use.</string>
+ <string name="permgroupupgraderequestdetail_sensors">This app wants to access sensor data about your vital signs all the time, even when you\u2019re not using the app. To make this change, <annotation id="link">go to settings.</annotation></string>
<!-- Message shown to the user when the apps requests permission to use the bosy sensors while app is in foreground and background. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
<string name="permgroupbackgroundrequest_sensors">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access the sensor data about your vital signs?</string>
@@ -1521,6 +1530,8 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
<string name="remove_microphone_qs">Remove microphone permission</string>
<!-- Label to manage service in safety center QS page [CHAR LIMIT=50] -->
<string name="manage_service_qs">Manage service</string>
+ <!-- Label to manage permissions in safety center QS page [CHAR LIMIT=50] -->
+ <string name="manage_permissions_qs">Manage permissions</string>
<!-- Label for active usage by phone call in safety center QS page [CHAR LIMIT=50] -->
<string name="active_call_usage_qs">Being used by phone call</string>
<!-- Label for recent usage by phone call in safety center QS page [CHAR LIMIT=50] -->
diff --git a/PermissionController/res/xml/roles.xml b/PermissionController/res/xml/roles.xml
index b28611866..802c2e336 100644
--- a/PermissionController/res/xml/roles.xml
+++ b/PermissionController/res/xml/roles.xml
@@ -578,6 +578,7 @@
<!-- Used for CTS testing -->
<permission name="android.permission.CREATE_VIRTUAL_DEVICE" minSdkVersion="33" />
<permission name="android.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE" />
+ <permission name="android.permission.ACCESS_AMBIENT_CONTEXT_EVENT" minSdkVersion="33"/>
<permission name="android.permission.PERFORM_IMS_SINGLE_REGISTRATION" />
<permission name="android.permission.BACKGROUND_CAMERA" />
<permission name="android.permission.RECORD_BACKGROUND_AUDIO" />
@@ -685,6 +686,7 @@
visible="false">
<permissions>
<permission name="android.permission.SYSTEM_APPLICATION_OVERLAY" />
+ <permission name="android.permission.OBSERVE_SENSOR_PRIVACY" />
</permissions>
</role>
@@ -742,7 +744,6 @@
<permission name="android.permission.MANAGE_APP_PREDICTIONS" />
<permission name="android.permission.UNLIMITED_SHORTCUTS_API_CALLS" />
<permission name="android.permission.MANAGE_SEARCH_UI" />
- <permission name="android.permission.MANAGE_WALLPAPER_EFFECTS_GENERATION" minSdkVersion="33" />
<permission name="android.permission.READ_EXTERNAL_STORAGE" />
<permission name="android.permission.READ_PEOPLE_DATA" />
<permission name="android.permission.READ_GLOBAL_APP_SEARCH_DATA" />
@@ -905,6 +906,7 @@
<permissions>
<permission name="android.permission.MANAGE_UI_TRANSLATION" />
<permission name="android.permission.SYSTEM_APPLICATION_OVERLAY" />
+ <permission name="android.permission.READ_CLIPBOARD_IN_BACKGROUND" minSdkVersion="33" />
</permissions>
</role>
@@ -1103,12 +1105,30 @@
-->
<role
name="android.app.role.DEVICE_POLICY_MANAGEMENT"
+ behavior="DevicePolicyManagementRoleBehavior"
defaultHolders="config_devicePolicyManagement"
exclusive="true"
minSdkVersion="33"
static="true"
systemOnly="false"
visible="false">
+ <required-components>
+ <activity permission="android.permission.LAUNCH_DEVICE_MANAGER_SETUP">
+ <intent-filter>
+ <action name="android.app.action.ROLE_HOLDER_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE" />
+ </intent-filter>
+ </activity>
+ <activity permission="android.permission.LAUNCH_DEVICE_MANAGER_SETUP">
+ <intent-filter>
+ <action name="android.app.action.ROLE_HOLDER_PROVISION_MANAGED_PROFILE" />
+ </intent-filter>
+ </activity>
+ <activity permission="android.permission.LAUNCH_DEVICE_MANAGER_SETUP">
+ <intent-filter>
+ <action name="android.app.action.ROLE_HOLDER_PROVISION_FINALIZATION" />
+ </intent-filter>
+ </activity>
+ </required-components>
<permissions>
<permission-set name="notifications" />
<permission name="android.permission.BIND_DEVICE_ADMIN" />
@@ -1260,13 +1280,13 @@
~ A role for the package that handles AI features for the settings app
-->
<role
- name="android.app.role.SETTINGS_INTELLIGENCE"
- defaultHolders="config_settingsIntelligencePackageName"
+ name="android.app.role.SYSTEM_SETTINGS_INTELLIGENCE"
+ defaultHolders="config_systemSettingsIntelligence"
exclusive="true"
minSdkVersion="33"
+ static="true"
systemOnly="true"
- visible="false"
- overrideUserWhenGranting="true">
+ visible="false">
<permissions>
<permission-set name="notifications" />
</permissions>
diff --git a/PermissionController/src/com/android/permissioncontroller/Constants.java b/PermissionController/src/com/android/permissioncontroller/Constants.java
index 1a12499ed..3fdaffe0b 100644
--- a/PermissionController/src/com/android/permissioncontroller/Constants.java
+++ b/PermissionController/src/com/android/permissioncontroller/Constants.java
@@ -49,13 +49,13 @@ public class Constants {
/**
* ID for the periodic job in
- * {@link com.android.permissioncontroller.permission.service.NotificationListenerCheck}.
+ * {@link com.android.permissioncontroller.permission.service.v33.NotificationListenerCheck}.
*/
public static final int PERIODIC_NOTIFICATION_LISTENER_CHECK_JOB_ID = 4;
/**
* ID for the on-demand, but delayed job in
- * {@link com.android.permissioncontroller.permission.service.NotificationListenerCheck}.
+ * {@link com.android.permissioncontroller.permission.service.v33.NotificationListenerCheck}.
*/
public static final int NOTIFICATION_LISTENER_CHECK_JOB_ID = 5;
@@ -70,7 +70,7 @@ public class Constants {
/**
* Name of file to containing the packages we already showed a notification for.
*
- * @see com.android.permissioncontroller.permission.service.NotificationListenerCheck
+ * @see com.android.permissioncontroller.permission.service.v33.NotificationListenerCheck
*/
public static final String NOTIFICATION_LISTENER_CHECK_ALREADY_NOTIFIED_FILE =
"packages_already_notified_notification_listener";
@@ -95,7 +95,7 @@ public class Constants {
/**
* ID for notification shown by
- * {@link com.android.permissioncontroller.permission.service.NotificationListenerCheck}.
+ * {@link com.android.permissioncontroller.permission.service.v33.NotificationListenerCheck}.
*/
public static final int NOTIFICATION_LISTENER_CHECK_NOTIFICATION_ID = 3;
@@ -122,7 +122,7 @@ public class Constants {
/**
* Channel of the notifications shown by
* {@link com.android.permissioncontroller.permission.service.LocationAccessCheck},
- * {@link com.android.permissioncontroller.permission.service.NotificationListenerCheck},
+ * {@link com.android.permissioncontroller.permission.service.v33.NotificationListenerCheck},
* {@link com.android.permissioncontroller.hibernation.HibernationPolicyKt}, and
* {@link com.android.permissioncontroller.auto.DrivingDecisionReminderService}
*/
@@ -149,7 +149,7 @@ public class Constants {
/**
* Key in the generic shared preferences that stores when the last notification was shown by
- * {@link com.android.permissioncontroller.permission.service.NotificationListenerCheck}
+ * {@link com.android.permissioncontroller.permission.service.v33.NotificationListenerCheck}
*/
public static final String KEY_LAST_NOTIFICATION_LISTENER_NOTIFICATION_SHOWN =
"last_notification_listener_notification_shown";
diff --git a/PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt b/PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt
index f4ff49081..daf0ba8c7 100644
--- a/PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt
+++ b/PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt
@@ -23,18 +23,22 @@ import android.app.PendingIntent
import android.app.Service
import android.car.Car
import android.car.drivingstate.CarUxRestrictionsManager
+import android.content.ComponentName
import android.content.Context
import android.content.Intent
+import android.content.pm.PackageManager
import android.os.Bundle
import android.os.IBinder
import android.os.Process
import android.os.UserHandle
import android.permission.PermissionManager
+import android.provider.Settings
import android.text.BidiFormatter
import androidx.annotation.VisibleForTesting
import com.android.permissioncontroller.Constants
import com.android.permissioncontroller.DumpableLog
import com.android.permissioncontroller.R
+import com.android.permissioncontroller.permission.utils.KotlinUtils
import com.android.permissioncontroller.permission.utils.KotlinUtils.getPackageLabel
import com.android.permissioncontroller.permission.utils.KotlinUtils.getPermGroupLabel
import com.android.permissioncontroller.permission.utils.StringUtils
@@ -63,6 +67,7 @@ class DrivingDecisionReminderService : Service() {
companion object {
private const val LOG_TAG = "DrivingDecisionReminderService"
+ private const val SETTINGS_PACKAGE_NAME_FALLBACK = "com.android.settings"
const val EXTRA_PACKAGE_NAME = "package_name"
const val EXTRA_PERMISSION_GROUP = "permission_group"
@@ -257,13 +262,27 @@ class DrivingDecisionReminderService : Service() {
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_UPDATE_CURRENT or
PendingIntent.FLAG_IMMUTABLE)
+ val settingsDrawable = KotlinUtils.getBadgedPackageIcon(
+ application,
+ getSettingsPackageName(applicationContext.packageManager),
+ permissionReminders.first().user)
+ val settingsIcon = if (settingsDrawable != null) {
+ KotlinUtils.convertToBitmap(settingsDrawable)
+ } else {
+ null
+ }
+
val b = Notification.Builder(this, Constants.PERMISSION_REMINDER_CHANNEL_ID)
.setContentTitle(title)
.setContentText(body)
.setSmallIcon(R.drawable.ic_settings_24dp)
+ .setLargeIcon(settingsIcon)
.setColor(getColor(android.R.color.system_notification_accent_color))
.setAutoCancel(true)
.setContentIntent(pendingIntent)
+ .addExtras(Bundle().apply {
+ putBoolean("com.android.car.notification.EXTRA_USE_LAUNCHER_ICON", false)
+ })
// Auto doesn't show icons for actions
.addAction(Notification.Action.Builder(/* icon= */ null,
getString(R.string.go_to_settings), pendingIntent).build())
@@ -274,4 +293,10 @@ class DrivingDecisionReminderService : Service() {
}
return b.build()
}
+
+ private fun getSettingsPackageName(pm: PackageManager): String {
+ val settingsIntent = Intent(Settings.ACTION_SETTINGS)
+ val settingsComponent: ComponentName? = settingsIntent.resolveActivity(pm)
+ return settingsComponent?.packageName ?: SETTINGS_PACKAGE_NAME_FALLBACK
+ }
} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/hibernation/HibernationPolicy.kt b/PermissionController/src/com/android/permissioncontroller/hibernation/HibernationPolicy.kt
index 15693d4e2..98d79aaa0 100644
--- a/PermissionController/src/com/android/permissioncontroller/hibernation/HibernationPolicy.kt
+++ b/PermissionController/src/com/android/permissioncontroller/hibernation/HibernationPolicy.kt
@@ -65,6 +65,7 @@ import androidx.lifecycle.MutableLiveData
import androidx.preference.PreferenceManager
import com.android.modules.utils.build.SdkLevel
import com.android.permissioncontroller.Constants
+import com.android.permissioncontroller.DeviceUtils
import com.android.permissioncontroller.DumpableLog
import com.android.permissioncontroller.PermissionControllerApplication
import com.android.permissioncontroller.R
@@ -623,6 +624,7 @@ class HibernationJobService : JobService() {
notifContent = getString(R.string.auto_revoke_permission_notification_content)
}
+ // Notification won't appear on TV, because notifications are considered distruptive on TV
val b = Notification.Builder(this, Constants.PERMISSION_REMINDER_CHANNEL_ID)
.setContentTitle(notifTitle)
.setContentText(notifContent)
@@ -631,7 +633,6 @@ class HibernationJobService : JobService() {
.setColor(getColor(android.R.color.system_notification_accent_color))
.setAutoCancel(true)
.setContentIntent(pendingIntent)
- .extend(Notification.TvExtender())
Utils.getSettingsLabelForNotifications(applicationContext.packageManager)?.let {
settingsLabel ->
val extras = Bundle()
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/TEST_MAPPING b/PermissionController/src/com/android/permissioncontroller/permission/TEST_MAPPING
index ec4ede804..6b89bc2f7 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/TEST_MAPPING
+++ b/PermissionController/src/com/android/permissioncontroller/permission/TEST_MAPPING
@@ -9,18 +9,20 @@
]
},
{
- "name": "CtsPermission3TestCases",
+ "name": "CtsOsTestCases",
"options": [
{
- "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+ "include-filter": "android.os.cts.AutoRevokeTest"
}
]
- },
+ }
+ ],
+ "presubmit-large": [
{
- "name": "CtsOsTestCases",
+ "name": "CtsPermission3TestCases",
"options": [
{
- "include-filter": "android.os.cts.AutoRevokeTest"
+ "exclude-annotation": "android.platform.test.annotations.FlakyTest"
}
]
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/AppPermissionGroup.java b/PermissionController/src/com/android/permissioncontroller/permission/model/AppPermissionGroup.java
index 9c1af7fa2..661da070d 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/model/AppPermissionGroup.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/model/AppPermissionGroup.java
@@ -34,6 +34,7 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
+import android.os.Binder;
import android.os.Build;
import android.os.UserHandle;
import android.permission.PermissionManager;
@@ -732,6 +733,21 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
* the ONE_TIME flag to return true
*/
public boolean areRuntimePermissionsGranted(String[] filterPermissions, boolean asOneTime) {
+ return areRuntimePermissionsGranted(filterPermissions, asOneTime, true);
+ }
+
+ /**
+ * Returns true if at least one of the permissions in filterPermissions (or the entire
+ * permission group if null) should be considered granted and satisfy the requirements
+ * described by asOneTime and includingAppOp.
+ *
+ * @param filterPermissions the permissions to check for, null for all in this group
+ * @param asOneTime add the requirement that the granted permission must have the ONE_TIME flag
+ * @param includingAppOp add the requirement that if the granted permissions has a
+ * corresponding AppOp, it must be allowed.
+ */
+ public boolean areRuntimePermissionsGranted(String[] filterPermissions, boolean asOneTime,
+ boolean includingAppOp) {
if (LocationUtils.isLocationGroupAndProvider(mContext, mName, mPackageInfo.packageName)) {
return LocationUtils.isLocationEnabled(mContext) && !asOneTime;
}
@@ -748,7 +764,9 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
&& !ArrayUtils.contains(filterPermissions, permission.getName())) {
continue;
}
- if (permission.isGrantedIncludingAppOp() && (!asOneTime || permission.isOneTime())) {
+ boolean isGranted = includingAppOp ? permission.isGrantedIncludingAppOp()
+ : permission.isGranted();
+ if (isGranted && (!asOneTime || permission.isOneTime())) {
return true;
}
}
@@ -756,7 +774,7 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
// If asOneTime is true and none of the foreground permissions are one-time, but some
// background permissions are, then we still want to return true.
return mBackgroundPermissions.areRuntimePermissionsGranted(filterPermissions,
- asOneTime);
+ asOneTime, includingAppOp);
}
return false;
}
@@ -1521,20 +1539,26 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
}
String packageName = mPackageInfo.packageName;
- if (areRuntimePermissionsGranted(null, true)) {
- if (SdkLevel.isAtLeastT()) {
- mContext.getSystemService(PermissionManager.class)
- .startOneTimePermissionSession(packageName,
- Utils.getOneTimePermissionsTimeout(),
- Utils.getOneTimePermissionsKilledDelay(mIsSelfRevoked),
- ONE_TIME_PACKAGE_IMPORTANCE_LEVEL_TO_RESET_TIMER,
- ONE_TIME_PACKAGE_IMPORTANCE_LEVEL_TO_KEEP_SESSION_ALIVE);
- } else {
- mContext.getSystemService(PermissionManager.class)
- .startOneTimePermissionSession(packageName,
- Utils.getOneTimePermissionsTimeout(),
- ONE_TIME_PACKAGE_IMPORTANCE_LEVEL_TO_RESET_TIMER,
- ONE_TIME_PACKAGE_IMPORTANCE_LEVEL_TO_KEEP_SESSION_ALIVE);
+ if (areRuntimePermissionsGranted(null, true, false)) {
+ // Required to read device config in Utils.getOneTimePermissions*().
+ final long token = Binder.clearCallingIdentity();
+ try {
+ if (SdkLevel.isAtLeastT()) {
+ mContext.getSystemService(PermissionManager.class)
+ .startOneTimePermissionSession(packageName,
+ Utils.getOneTimePermissionsTimeout(),
+ Utils.getOneTimePermissionsKilledDelay(mIsSelfRevoked),
+ ONE_TIME_PACKAGE_IMPORTANCE_LEVEL_TO_RESET_TIMER,
+ ONE_TIME_PACKAGE_IMPORTANCE_LEVEL_TO_KEEP_SESSION_ALIVE);
+ } else {
+ mContext.getSystemService(PermissionManager.class)
+ .startOneTimePermissionSession(packageName,
+ Utils.getOneTimePermissionsTimeout(),
+ ONE_TIME_PACKAGE_IMPORTANCE_LEVEL_TO_RESET_TIMER,
+ ONE_TIME_PACKAGE_IMPORTANCE_LEVEL_TO_KEEP_SESSION_ALIVE);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
} else {
mContext.getSystemService(PermissionManager.class)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java
index 1e60708f8..ff2559933 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java
@@ -654,14 +654,18 @@ public final class PermissionControllerServiceImpl extends PermissionControllerL
for (String permission : permissions) {
AppPermissionGroup group = AppPermissionGroup.create(this, packageInfo, permission,
true);
- if (group != null && group.isOneTime()) {
- groups.add(group);
+ if (group != null) {
+ AppPermissionGroup bgGroup = group.getBackgroundPermissions();
+ boolean isBgGroupOneTime = bgGroup != null && bgGroup.isOneTime();
+ if (group.isOneTime() || isBgGroupOneTime) {
+ groups.add(group);
+ }
}
}
long requestId = Utils.getValidSessionId();
for (AppPermissionGroup group : groups) {
AppPermissionGroup bgGroup = group.getBackgroundPermissions();
- if (group.areRuntimePermissionsGranted()) {
+ if (group.areRuntimePermissionsGranted(null, true, false)) {
logOneTimeSessionRevoke(packageName, uid, group, requestId);
// Revoke only one time granted permissions if not all
List<String> oneTimeGrantedPermissions = group.getPermissions().stream()
@@ -698,10 +702,10 @@ public final class PermissionControllerServiceImpl extends PermissionControllerL
}
group.persistChanges(false, ONE_TIME_PERMISSION_REVOKED_REASON);
if (bgGroup != null) {
- bgGroup.persistChanges(false, ONE_TIME_PERMISSION_REVOKED_REASON);
if (!bgGroup.supportsOneTimeGrant()) {
bgGroup.setOneTime(false);
}
+ bgGroup.persistChanges(false, ONE_TIME_PERMISSION_REVOKED_REASON);
}
}
}
@@ -759,7 +763,7 @@ public final class PermissionControllerServiceImpl extends PermissionControllerL
}
@Override
- public void onRevokeOwnPermissionsOnKill(@NonNull String packageName,
+ public void onRevokeSelfPermissionsOnKill(@NonNull String packageName,
@NonNull List<String> permissions, @NonNull Runnable callback) {
PackageInfo pkgInfo = getPkgInfo(packageName);
if (pkgInfo == null) {
@@ -771,18 +775,17 @@ public final class PermissionControllerServiceImpl extends PermissionControllerL
for (String permName : permissions) {
AppPermissionGroup group = app.getGroupForPermission(permName);
if (group == null) {
- throw new SecurityException("Cannot revoke permission " + permName + " for package "
- + packageName + " since " + permName + " does not belong to a permission "
- + "group");
+ throw new IllegalArgumentException("Cannot revoke permission " + permName
+ + " for package " + packageName + " since " + permName
+ + " does not belong to a permission group");
+ }
+ if (!group.doesSupportRuntimePermissions()) {
+ throw new IllegalArgumentException("Cannot revoke permission " + permName
+ + " for package " + packageName + " since it is not a runtime permission");
}
Permission perm = group.getPermission(permName);
if (!perm.isGranted()) {
- throw new SecurityException("Cannot revoke permission " + permName + " for package "
- + packageName + " since " + packageName + " does not hold it");
- }
- if (!group.doesSupportRuntimePermissions()) {
- throw new SecurityException("Cannot revoke permission " + permName + " for package "
- + packageName + " since it is not a runtime permission");
+ continue;
}
perm.setOneTime(true);
groups.add(group);
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceModel.kt
index 257bf8bfb..efa103eef 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceModel.kt
@@ -23,6 +23,7 @@ import android.permission.PermissionControllerManager.COUNT_WHEN_SYSTEM
import android.permission.PermissionControllerManager.HIBERNATION_ELIGIBILITY_ELIGIBLE
import android.permission.PermissionControllerManager.HIBERNATION_ELIGIBILITY_EXEMPT_BY_SYSTEM
import android.permission.PermissionControllerManager.HIBERNATION_ELIGIBILITY_EXEMPT_BY_USER
+import android.permission.PermissionControllerManager.HIBERNATION_ELIGIBILITY_UNKNOWN
import androidx.core.util.Consumer
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LiveData
@@ -315,15 +316,20 @@ class PermissionControllerServiceModel(private val service: PermissionController
val packageLiveData = LightPackageInfoLiveData[packageName, user]
observeAndCheckForLifecycleState(packageLiveData) { pkg ->
GlobalScope.launch(Main.immediate) {
- val exemptBySystem = isPackageHibernationExemptBySystem(pkg!!, user)
- val exemptByUser = isPackageHibernationExemptByUser(
- PermissionControllerApplication.get(), pkg!!)
- val eligibility = when {
- !exemptBySystem && !exemptByUser -> HIBERNATION_ELIGIBILITY_ELIGIBLE
- exemptBySystem -> HIBERNATION_ELIGIBILITY_EXEMPT_BY_SYSTEM
- else -> HIBERNATION_ELIGIBILITY_EXEMPT_BY_USER
+ if (pkg == null) {
+ // Possible that app is uninstalled or user is switched
+ callback.accept(HIBERNATION_ELIGIBILITY_UNKNOWN)
+ } else {
+ val exemptBySystem = isPackageHibernationExemptBySystem(pkg, user)
+ val exemptByUser = isPackageHibernationExemptByUser(
+ PermissionControllerApplication.get(), pkg)
+ val eligibility = when {
+ !exemptBySystem && !exemptByUser -> HIBERNATION_ELIGIBILITY_ELIGIBLE
+ exemptBySystem -> HIBERNATION_ELIGIBILITY_EXEMPT_BY_SYSTEM
+ else -> HIBERNATION_ELIGIBILITY_EXEMPT_BY_USER
+ }
+ callback.accept(eligibility)
}
- callback.accept(eligibility)
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/NotificationListenerCheck.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/v33/NotificationListenerCheck.kt
index 1f1bcd0e6..5ab85d36f 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/NotificationListenerCheck.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/v33/NotificationListenerCheck.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.permissioncontroller.permission.service
+package com.android.permissioncontroller.permission.service.v33
import android.app.Notification
import android.app.NotificationChannel
@@ -33,17 +33,22 @@ import android.content.Context
import android.content.Context.MODE_PRIVATE
import android.content.Intent
import android.content.Intent.EXTRA_COMPONENT_NAME
+import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
+import android.content.Intent.FLAG_RECEIVER_FOREGROUND
import android.content.SharedPreferences
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
+import android.os.Build
import android.os.Bundle
-import android.os.UserHandle
import android.os.UserManager
import android.provider.DeviceConfig
+import android.safetycenter.SafetyCenterManager
import android.service.notification.StatusBarNotification
import android.util.ArraySet
import android.util.Log
+import androidx.annotation.ChecksSdkIntAtLeast
import androidx.annotation.GuardedBy
+import androidx.annotation.RequiresApi
import androidx.annotation.VisibleForTesting
import androidx.annotation.WorkerThread
import androidx.core.util.Preconditions
@@ -58,6 +63,7 @@ import com.android.permissioncontroller.Constants.PERIODIC_NOTIFICATION_LISTENER
import com.android.permissioncontroller.Constants.PREFERENCES_FILE
import com.android.permissioncontroller.R
import com.android.permissioncontroller.permission.utils.Utils
+import com.android.permissioncontroller.permission.utils.Utils.getSystemServiceSafe
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Dispatchers.Default
import kotlinx.coroutines.GlobalScope
@@ -104,16 +110,11 @@ private val DEFAULT_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS = DAYS.toMillis(
private val DEFAULT_NOTIFICATION_LISTENER_CHECK_PACKAGE_INTERVAL_MILLIS = DAYS.toMillis(90)
-private fun checkNotificationListenerCheckEnabled(): Boolean {
+private fun isNotificationListenerCheckFlagEnabled(): Boolean {
return DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_PRIVACY,
PROPERTY_NOTIFICATION_LISTENER_CHECK_ENABLED,
- false
- )
-}
-
-private fun checkNotificationListenerSupported(): Boolean {
- return SdkLevel.isAtLeastT()
+ false)
}
/**
@@ -185,7 +186,9 @@ private fun getPackageNotificationIntervalMillis(): Long {
* @param context Used to resolve managers
* @param shouldCancel If supplied, can be used to interrupt long-running operations
*/
-class NotificationListenerCheck(
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+@VisibleForTesting
+internal class NotificationListenerCheckInternal(
context: Context,
private val shouldCancel: BooleanSupplier?
) {
@@ -194,8 +197,6 @@ class NotificationListenerCheck(
private val random = Random()
private val sharedPrefs: SharedPreferences =
parentUserContext.getSharedPreferences(PREFERENCES_FILE, MODE_PRIVATE)
- private val userManager: UserManager =
- Utils.getSystemServiceSafe(parentUserContext, UserManager::class.java)
companion object {
/** Lock required for all public methods */
@@ -210,20 +211,8 @@ class NotificationListenerCheck(
@WorkerThread
internal suspend fun getEnabledNotificationListenersAndNotifyIfNeeded(
params: JobParameters,
- service: NotificationListenerCheckJobService
+ service: NotificationListenerCheck.NotificationListenerCheckJobService
) {
- if (!checkNotificationListenerCheckEnabled()) {
- if (DEBUG) Log.d(TAG, "NotificationListenerCheck disabled, finishing job")
- service.jobFinished(params, false)
- return
- }
-
- if (!isRunningInParentProfile()) {
- // Profile parent handles child profiles too.
- if (DEBUG) Log.d(TAG, "NotificationListenerCheck only supported from parent profile")
- return
- }
-
nlsLock.withLock {
try {
getEnabledNotificationListenersAndNotifyIfNeededLocked()
@@ -276,7 +265,7 @@ class NotificationListenerCheck(
// Get all enabled NotificationListenerService components for primary user. NLS from managed
// profiles are never bound.
val enabledNotificationListeners =
- Utils.getSystemServiceSafe(parentUserContext, NotificationManager::class.java)
+ getSystemServiceSafe(parentUserContext, NotificationManager::class.java)
.enabledNotificationListeners
if (DEBUG) {
@@ -304,7 +293,7 @@ class NotificationListenerCheck(
*/
@WorkerThread
@VisibleForTesting
- internal suspend fun loadNotifiedComponentsLocked(): ArraySet<NlsComponent> {
+ suspend fun loadNotifiedComponentsLocked(): ArraySet<NlsComponent> {
return withContext(Dispatchers.IO) {
try {
BufferedReader(
@@ -426,27 +415,31 @@ class NotificationListenerCheck(
*/
internal suspend fun markAsNotified(componentName: ComponentName) {
nlsLock.withLock {
- val notifiedComponentsMap: MutableMap<ComponentName, NlsComponent> =
- loadNotifiedComponentsLocked()
- .associateBy({ it.componentName }, { it })
- .toMutableMap()
-
- // NlsComponent don't compare timestamps, so remove existing NlsComponent if present and
- // then add again
- val currentComponent: NlsComponent? = notifiedComponentsMap.remove(componentName)
- val componentToMarkNotified: NlsComponent =
- if (currentComponent != null) {
- // Copy the current notified component and only update the notificationShownTime
- currentComponent.copy(notificationShownTime = currentTimeMillis())
- } else {
- // No previoulys notified component, create new one
- NlsComponent(componentName, notificationShownTime = currentTimeMillis())
- }
- notifiedComponentsMap[componentName] = componentToMarkNotified
- persistNotifiedComponentsLocked(notifiedComponentsMap.values)
+ markAsNotifiedLocked(componentName)
}
}
+ private suspend fun markAsNotifiedLocked(componentName: ComponentName) {
+ val notifiedComponentsMap: MutableMap<ComponentName, NlsComponent> =
+ loadNotifiedComponentsLocked()
+ .associateBy({ it.componentName }, { it })
+ .toMutableMap()
+
+ // NlsComponent don't compare timestamps, so remove existing NlsComponent if present and
+ // then add again
+ val currentComponent: NlsComponent? = notifiedComponentsMap.remove(componentName)
+ val componentToMarkNotified: NlsComponent =
+ if (currentComponent != null) {
+ // Copy the current notified component and only update the notificationShownTime
+ currentComponent.copy(notificationShownTime = currentTimeMillis())
+ } else {
+ // No previoulys notified component, create new one
+ NlsComponent(componentName, notificationShownTime = currentTimeMillis())
+ }
+ notifiedComponentsMap[componentName] = componentToMarkNotified
+ persistNotifiedComponentsLocked(notifiedComponentsMap.values)
+ }
+
@Throws(InterruptedException::class)
private suspend fun postSystemNotificationIfNeeded(components: List<ComponentName>) {
val componentsInternal = components.toMutableList()
@@ -496,6 +489,7 @@ class NotificationListenerCheck(
createPermissionReminderChannel()
createNotificationForNotificationListener(componentToNotifyFor, pkgInfo)
+ markAsNotifiedLocked(componentToNotifyFor)
}
/**
@@ -519,7 +513,7 @@ class NotificationListenerCheck(
NotificationManager.IMPORTANCE_LOW
)
- val notificationManager = Utils.getSystemServiceSafe(
+ val notificationManager = getSystemServiceSafe(
parentUserContext,
NotificationManager::class.java
)
@@ -546,16 +540,18 @@ class NotificationListenerCheck(
sessionId = Random().nextLong()
}
- val deleteIntent = Intent(parentUserContext, NotificationDeleteHandler::class.java).apply {
+ val deleteIntent = Intent(parentUserContext,
+ NotificationListenerCheck.NotificationDeleteHandler::class.java).apply {
putExtra(EXTRA_COMPONENT_NAME, componentName)
putExtra(EXTRA_SESSION_ID, sessionId)
- flags = Intent.FLAG_RECEIVER_FOREGROUND
+ flags = FLAG_RECEIVER_FOREGROUND
}
- val clickIntent = Intent(parentUserContext, NotificationClickHandler::class.java).apply {
+ val clickIntent = Intent(Intent.ACTION_SAFETY_CENTER).apply {
+ // TODO(b/217566029): update with EXTRA_SAFETY_SOURCE_ISSUE_ID and EXTRA_SAFETY_SOURCE_ID
putExtra(EXTRA_COMPONENT_NAME, componentName)
putExtra(EXTRA_SESSION_ID, sessionId)
- flags = Intent.FLAG_RECEIVER_FOREGROUND
+ flags = FLAG_ACTIVITY_NEW_TASK
}
val title =
@@ -573,8 +569,7 @@ class NotificationListenerCheck(
.setContentText(text)
// Ensure entire text can be displayed, instead of being truncated to one line
.setStyle(Notification.BigTextStyle().bigText(text))
- // TODO(b/213357911): replace with Safety Center resource
- .setSmallIcon(R.drawable.ic_pin_drop)
+ .setSmallIcon(android.R.drawable.ic_safety_protection)
// TODO(b/213357911): replace with Safety Center resource
.setColor(
parentUserContext.getColor(R.color.safety_center_info))
@@ -586,22 +581,19 @@ class NotificationListenerCheck(
)
)
.setContentIntent(
- PendingIntent.getBroadcast(
+ PendingIntent.getActivity(
parentUserContext, 0, clickIntent,
FLAG_ONE_SHOT or FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE
)
)
- // TODO(b/213357911): replace with Safety Center resource
- val appName = Utils.getSettingsLabelForNotifications(packageManager)
- if (appName != null) {
- val extras = Bundle()
- extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, appName.toString())
- b.addExtras(extras)
- }
+ val appName = parentUserContext.getString(android.R.string.safety_protection_display_text)
+ val appNameExtras = Bundle()
+ appNameExtras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, appName)
+ b.addExtras(appNameExtras)
val notificationManager =
- Utils.getSystemServiceSafe(parentUserContext, NotificationManager::class.java)
+ getSystemServiceSafe(parentUserContext, NotificationManager::class.java)
notificationManager.notify(pkgName, NOTIFICATION_LISTENER_CHECK_NOTIFICATION_ID, b.build())
Log.v(TAG, "Notification listener check notification shown with sessionId=" +
@@ -623,7 +615,7 @@ class NotificationListenerCheck(
*/
private fun getCurrentlyShownNotificationLocked(): StatusBarNotification? {
val notifications =
- Utils.getSystemServiceSafe(parentUserContext, NotificationManager::class.java)
+ getSystemServiceSafe(parentUserContext, NotificationManager::class.java)
.activeNotifications
for (notification in notifications) {
@@ -642,7 +634,7 @@ class NotificationListenerCheck(
private suspend fun removeNotificationsForPackage(pkg: String) {
val notification: StatusBarNotification? = getCurrentlyShownNotificationLocked()
if (notification != null && notification.tag == pkg) {
- Utils.getSystemServiceSafe(parentUserContext, NotificationManager::class.java)
+ getSystemServiceSafe(parentUserContext, NotificationManager::class.java)
.cancel(pkg, NOTIFICATION_LISTENER_CHECK_NOTIFICATION_ID)
}
}
@@ -658,21 +650,28 @@ class NotificationListenerCheck(
}
/**
- * Check if the current user is the profile parent.
+ * An immutable data class containing a [ComponentName] and timestamps for notification and
+ * signal resolved.
*
- * @return `true` if the current user is the profile parent.
+ * @param componentName The component name of the notification listener
+ * @param notificationShownTime optional named parameter to set time of notification shown
+ * @param signalResolvedTime optional named parameter to set time of signal resolved
*/
- private fun isRunningInParentProfile(): Boolean {
- val user = UserHandle.of(UserHandle.myUserId())
- val parent: UserHandle? = userManager.getProfileParent(user)
- return parent == null || user == parent
- }
+ @VisibleForTesting
+ data class NlsComponent(
+ val componentName: ComponentName,
+ val notificationShownTime: Long = 0L,
+ val signalResolvedTime: Long = 0L
+ )
+}
+
+class NotificationListenerCheck {
/**
* Checks if a new notification should be shown.
*/
class NotificationListenerCheckJobService : JobService() {
- private var notificationListenerCheck: NotificationListenerCheck? = null
+ private var notificationListenerCheckInternal: NotificationListenerCheckInternal? = null
private val jobLock = Object()
/** We currently check if we should show a notification, the task executing the check */
@@ -681,12 +680,19 @@ class NotificationListenerCheck(
override fun onCreate() {
super.onCreate()
- notificationListenerCheck = NotificationListenerCheck(this, BooleanSupplier {
- synchronized(jobLock) {
- val job = addNotificationListenerNotificationIfNeededJob
- return@BooleanSupplier job?.isCancelled ?: false
- }
- })
+
+ if (!checkNotificationListenerCheckEnabled(this)) {
+ // NotificationListenerCheck not enabled. End job.
+ return
+ }
+
+ notificationListenerCheckInternal =
+ NotificationListenerCheckInternal(this, BooleanSupplier {
+ synchronized(jobLock) {
+ val job = addNotificationListenerNotificationIfNeededJob
+ return@BooleanSupplier job?.isCancelled ?: false
+ }
+ })
}
/**
@@ -694,19 +700,25 @@ class NotificationListenerCheck(
*
* @param params Not used other than for interacting with job scheduling
*
- * @return `false` iff another check if already running
+ * @return `false` if another check is already running, or if SDK Check fails (below T)
*/
override fun onStartJob(params: JobParameters): Boolean {
+ if (!checkNotificationListenerCheckEnabled(this)) {
+ // NotificationListenerCheck not enabled. End job.
+ return false
+ }
+
synchronized(jobLock) {
if (addNotificationListenerNotificationIfNeededJob != null) {
if (DEBUG) Log.d(TAG, "Job already running")
return false
}
addNotificationListenerNotificationIfNeededJob = GlobalScope.launch(Default) {
- notificationListenerCheck?.getEnabledNotificationListenersAndNotifyIfNeeded(
- params,
- this@NotificationListenerCheckJobService
- ) ?: jobFinished(params, true)
+ notificationListenerCheckInternal
+ ?.getEnabledNotificationListenersAndNotifyIfNeeded(
+ params,
+ this@NotificationListenerCheckJobService
+ ) ?: jobFinished(params, true)
}
}
return true
@@ -743,19 +755,19 @@ class NotificationListenerCheck(
* On boot set up a periodic job that starts checks.
*/
class SetupPeriodicNotificationListenerCheck : BroadcastReceiver() {
+
override fun onReceive(context: Context, intent: Intent) {
- if (!checkNotificationListenerSupported()) {
+ if (!checkNotificationListenerCheckSupported()) {
+ // Notification Listener Check not supported. Exit.
return
}
- val notificationListenerCheck = NotificationListenerCheck(context, null)
- val jobScheduler = Utils.getSystemServiceSafe(context, JobScheduler::class.java)
-
- if (!notificationListenerCheck.isRunningInParentProfile()) {
+ if (isProfile(context)) {
// Profile parent handles child profiles too.
return
}
+ val jobScheduler = getSystemServiceSafe(context, JobScheduler::class.java)
if (jobScheduler.getPendingJob(PERIODIC_NOTIFICATION_LISTENER_CHECK_JOB_ID) == null) {
val job =
JobInfo.Builder(
@@ -779,36 +791,19 @@ class NotificationListenerCheck(
}
/**
- * Show the notification listener permission switch when the notification is clicked.
+ * Handle the case where the notification is swiped away without further interaction.
*/
- class NotificationClickHandler() : BroadcastReceiver() {
+ class NotificationDeleteHandler : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
- val componentName =
- Utils.getParcelableExtraSafe<ComponentName>(intent, EXTRA_COMPONENT_NAME)
- val sessionId = intent.getLongExtra(EXTRA_SESSION_ID, INVALID_SESSION_ID)
- GlobalScope.launch(Default) {
- NotificationListenerCheck(context, null).markAsNotified(componentName)
+ if (!checkNotificationListenerCheckEnabled(context)) {
+ return
}
- Log.v(
- TAG,
- "Notification listener check notification clicked with sessionId=$sessionId " +
- "component=${componentName.flattenToString()}"
- )
- // TODO(b/216365468): send users to safety center
- }
- }
-
- /**
- * Handle the case where the notification is swiped away without further interaction.
- */
- class NotificationDeleteHandler() : BroadcastReceiver() {
- override fun onReceive(context: Context, intent: Intent) {
val componentName =
Utils.getParcelableExtraSafe<ComponentName>(intent, EXTRA_COMPONENT_NAME)
val sessionId = intent.getLongExtra(EXTRA_SESSION_ID, INVALID_SESSION_ID)
GlobalScope.launch(Default) {
- NotificationListenerCheck(context, null).markAsNotified(componentName)
+ NotificationListenerCheckInternal(context, null).markAsNotified(componentName)
}
Log.v(
TAG,
@@ -831,7 +826,14 @@ class NotificationListenerCheck(
return
}
- if (!checkNotificationListenerSupported()) {
+ if (!checkNotificationListenerCheckEnabled(context)) {
+ return
+ }
+
+ if (isProfile(context)) {
+ if (DEBUG) {
+ Log.d(TAG, "NotificationListenerCheck only supports parent profile")
+ }
return
}
@@ -840,34 +842,34 @@ class NotificationListenerCheck(
if (DEBUG) Log.i(TAG, "Reset " + data.schemeSpecificPart)
GlobalScope.launch(Default) {
- NotificationListenerCheck(context, null).run {
- if (!this.isRunningInParentProfile()) {
- if (DEBUG) {
- Log.d(TAG, "NotificationListenerCheck only supports parent profile")
- }
- return@run
- }
-
+ NotificationListenerCheckInternal(context, null).run {
removePackageState(data.schemeSpecificPart)
-
// TODO(b/217566029): update Safety center action cards
}
}
}
}
- /**
- * An immutable data class containing a [ComponentName] and timestamps for notification and
- * signal resolved.
- *
- * @param componentName The component name of the notification listener
- * @param notificationShownTime optional named parameter to set time of notification shown
- * @param signalResolvedTime optional named parameter to set time of signal resolved
- */
- @VisibleForTesting
- internal data class NlsComponent(
- val componentName: ComponentName,
- val notificationShownTime: Long = 0L,
- val signalResolvedTime: Long = 0L
- )
+ companion object {
+ /** Notification Listener Check requires Android T or later*/
+ @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.TIRAMISU)
+ private fun checkNotificationListenerCheckSupported(): Boolean {
+ return SdkLevel.isAtLeastT()
+ }
+
+ /** Returns {@code true} when Notification listener check is supported, feature flag enabled and
+ * Safety Center enabled */
+ @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.TIRAMISU)
+ private fun checkNotificationListenerCheckEnabled(context: Context): Boolean {
+ return checkNotificationListenerCheckSupported() &&
+ isNotificationListenerCheckFlagEnabled() &&
+ getSystemServiceSafe(context, SafetyCenterManager::class.java).isSafetyCenterEnabled
+ }
+
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ private fun isProfile(context: Context): Boolean {
+ val userManager = getSystemServiceSafe(context, UserManager::class.java)
+ return userManager.isProfile
+ }
+ }
} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/v33/TEST_MAPPING b/PermissionController/src/com/android/permissioncontroller/permission/service/v33/TEST_MAPPING
new file mode 100644
index 000000000..c44286317
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/v33/TEST_MAPPING
@@ -0,0 +1,15 @@
+{
+ "postsubmit": [
+ {
+ "name": "CtsPermissionTestCases",
+ "options": [
+ {
+ "include-filter": "android.permission.cts.NotificationListenerCheckTest"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ]
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/AutoGrantPermissionsNotifier.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/AutoGrantPermissionsNotifier.java
index b6ca9f141..6d81983aa 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/AutoGrantPermissionsNotifier.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/AutoGrantPermissionsNotifier.java
@@ -19,15 +19,13 @@ package com.android.permissioncontroller.permission.ui;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
import static android.app.PendingIntent.getActivity;
-import static android.app.admin.DevicePolicyResources.Strings.PermissionController.LOCATION_AUTO_GRANTED_MESSAGE;
+import static android.app.admin.DevicePolicyResources.Strings.PermissionSettings.LOCATION_AUTO_GRANTED_MESSAGE;
import static android.content.Intent.ACTION_MANAGE_APP_PERMISSION;
import static android.content.Intent.EXTRA_PACKAGE_NAME;
import static android.content.Intent.EXTRA_PERMISSION_GROUP_NAME;
import static android.content.Intent.EXTRA_USER;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
-import static android.graphics.Bitmap.Config.ARGB_8888;
-import static android.graphics.Bitmap.createBitmap;
import static android.os.UserHandle.getUserHandleForUid;
import static com.android.permissioncontroller.Constants.ADMIN_AUTO_GRANTED_PERMISSIONS_ALERTING_NOTIFICATION_CHANNEL_ID;
@@ -41,15 +39,12 @@ import android.Manifest;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
-import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.UserHandle;
@@ -59,8 +54,9 @@ import android.util.ArraySet;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.modules.utils.build.SdkLevel;
import com.android.permissioncontroller.R;
+import com.android.permissioncontroller.permission.utils.KotlinUtils;
+import com.android.permissioncontroller.permission.utils.Utils;
import java.util.ArrayList;
@@ -144,7 +140,8 @@ public class AutoGrantPermissionsNotifier {
long sessionId = getValidSessionId();
Intent manageAppPermission = getSettingsPermissionIntent(sessionId);
- Bitmap pkgIconBmp = getPackageIcon(pm.getApplicationIcon(mPackageInfo.applicationInfo));
+ Bitmap pkgIconBmp = KotlinUtils.INSTANCE.convertToBitmap(
+ pm.getApplicationIcon(mPackageInfo.applicationInfo));
// Use the hash code of the package name string as a unique request code for
// PendingIntent.getActivity.
// To prevent multiple notifications related to different apps all leading to the same
@@ -158,18 +155,8 @@ public class AutoGrantPermissionsNotifier {
String title = mContext.getString(
R.string.auto_granted_location_permission_notification_title);
- String messageText;
- if (SdkLevel.isAtLeastT()) {
- DevicePolicyManager dpm = getSystemServiceSafe(mContext, DevicePolicyManager.class);
- messageText = dpm.getString(
- LOCATION_AUTO_GRANTED_MESSAGE,
- () -> mContext.getString(
- R.string.auto_granted_permission_notification_body, pkgLabel),
- pkgLabel);
- } else {
- messageText = mContext.getString(
- R.string.auto_granted_permission_notification_body, pkgLabel);
- }
+ String messageText = Utils.getEnterpriseString(mContext, LOCATION_AUTO_GRANTED_MESSAGE,
+ R.string.auto_granted_permission_notification_body, pkgLabel);
Notification.Builder b = (new Notification.Builder(mContext,
getNotificationChannelId(shouldNotifySilently))).setContentTitle(title)
.setContentText(messageText)
@@ -240,16 +227,6 @@ public class AutoGrantPermissionsNotifier {
AutoGrantPermissionsNotifier.class.getName());
}
- private @NonNull Bitmap getPackageIcon(@NonNull Drawable pkgIcon) {
- Bitmap pkgIconBmp = createBitmap(pkgIcon.getIntrinsicWidth(), pkgIcon.getIntrinsicHeight(),
- ARGB_8888);
- // Draw the icon so it can be displayed.
- Canvas canvas = new Canvas(pkgIconBmp);
- pkgIcon.setBounds(0, 0, pkgIcon.getIntrinsicWidth(), pkgIcon.getIntrinsicHeight());
- pkgIcon.draw(canvas);
- return pkgIconBmp;
- }
-
private String getNotificationChannelId(boolean shouldNotifySilently) {
if (shouldNotifySilently) {
return ADMIN_AUTO_GRANTED_PERMISSIONS_NOTIFICATION_CHANNEL_ID;
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
index 7639c2031..9ff92a1f4 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
@@ -46,6 +46,7 @@ import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.Window;
import android.view.WindowManager;
+import android.view.inputmethod.InputMethodManager;
import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;
@@ -496,7 +497,11 @@ public class GrantPermissionsActivity extends SettingsActivity
}
getWindow().setDimAmount(mOriginalDimAmount);
- mRootView.setVisibility(View.VISIBLE);
+ if (mRootView.getVisibility() == View.GONE) {
+ InputMethodManager manager = getSystemService(InputMethodManager.class);
+ manager.hideSoftInputFromWindow(mRootView.getWindowToken(), 0);
+ mRootView.setVisibility(View.VISIBLE);
+ }
}
@Override
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java
index 086a985bb..502c8b7d8 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java
@@ -422,8 +422,19 @@ public final class AppPermissionGroupsFragment extends SettingsWithLargeHeader i
mViewModel.setAutoRevoke(autoRevokeSwitch.isChecked());
return true;
});
- autoRevokeSwitch.setTitle(isHibernationEnabled() ? R.string.unused_apps_label
- : R.string.auto_revoke_label);
+
+ int switchTitleId;
+ if (isHibernationEnabled()) {
+ if (SdkLevel.isAtLeastT()) {
+ switchTitleId = R.string.unused_apps_label_v2;
+ autoRevokeSwitch.setSummary(R.string.unused_apps_summary);
+ } else {
+ switchTitleId = R.string.unused_apps_label;
+ }
+ } else {
+ switchTitleId = R.string.auto_revoke_label;
+ }
+ autoRevokeSwitch.setTitle(switchTitleId);
autoRevokeSwitch.setKey(AUTO_REVOKE_SWITCH_KEY);
autoRevokeCategory.addPreference(autoRevokeSwitch);
@@ -433,7 +444,9 @@ public final class AppPermissionGroupsFragment extends SettingsWithLargeHeader i
android.R.attr.colorControlNormal));
autoRevokeSummary.setKey(AUTO_REVOKE_SUMMARY_KEY);
if (isHibernationEnabled()) {
- autoRevokeCategory.setTitle(R.string.unused_apps);
+ autoRevokeCategory.setTitle(
+ SdkLevel.isAtLeastT() ? R.string.unused_apps_category_title
+ : R.string.unused_apps);
}
autoRevokeCategory.addPreference(autoRevokeSummary);
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.kt
index a14929499..6dc3ee096 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.kt
@@ -27,6 +27,7 @@ import android.graphics.Path
import android.graphics.PixelFormat
import android.graphics.PorterDuff
import android.graphics.PorterDuffXfermode
+import android.graphics.Typeface
import android.graphics.drawable.AnimatedImageDrawable
import android.graphics.drawable.Drawable
import android.graphics.drawable.Icon
@@ -420,6 +421,8 @@ class GrantPermissionsViewHandlerImpl(
null, null)
coarseOffDrawable?.start()
fineOnDrawable?.start()
+ fineRadioButton?.setTypeface(null, Typeface.BOLD)
+ coarseRadioButton?.setTypeface(null, Typeface.NORMAL)
} else {
coarseOffDrawable?.stop()
fineOnDrawable?.stop()
@@ -429,6 +432,8 @@ class GrantPermissionsViewHandlerImpl(
null, null)
coarseOnDrawable?.start()
fineOffDrawable?.start()
+ coarseRadioButton?.setTypeface(null, Typeface.BOLD)
+ fineRadioButton?.setTypeface(null, Typeface.NORMAL)
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionPreference.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionPreference.java
index 5d17c5e1e..658a82af5 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionPreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionPreference.java
@@ -16,16 +16,14 @@
package com.android.permissioncontroller.permission.ui.handheld;
-import static android.app.admin.DevicePolicyResources.Strings.PermissionController.BACKGROUND_ACCESS_DISABLED_BY_ADMIN_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.PermissionController.BACKGROUND_ACCESS_ENABLED_BY_ADMIN_MESSAGE;
-import static android.app.admin.DevicePolicyResources.Strings.PermissionController.FOREGROUND_ACCESS_ENABLED_BY_ADMIN_MESSAGE;
+import static android.app.admin.DevicePolicyResources.Strings.PermissionSettings.BACKGROUND_ACCESS_DISABLED_BY_ADMIN_MESSAGE;
+import static android.app.admin.DevicePolicyResources.Strings.PermissionSettings.BACKGROUND_ACCESS_ENABLED_BY_ADMIN_MESSAGE;
+import static android.app.admin.DevicePolicyResources.Strings.PermissionSettings.FOREGROUND_ACCESS_ENABLED_BY_ADMIN_MESSAGE;
import static com.android.permissioncontroller.permission.utils.Utils.getRequestMessage;
-import static com.android.permissioncontroller.permission.utils.Utils.getSystemServiceSafe;
import android.app.AlertDialog;
import android.app.Dialog;
-import android.app.admin.DevicePolicyManager;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.UserHandle;
@@ -36,7 +34,6 @@ import androidx.annotation.LayoutRes;
import androidx.fragment.app.DialogFragment;
import androidx.preference.PreferenceFragmentCompat;
-import com.android.modules.utils.build.SdkLevel;
import com.android.permissioncontroller.R;
import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup;
import com.android.permissioncontroller.permission.ui.model.ReviewPermissionsViewModel;
@@ -277,15 +274,21 @@ class PermissionPreference extends MultiTargetSwitchPreference {
if (summary.isEnterprise()) {
switch (summary.getMsg()) {
case ENABLED_BY_ADMIN_BACKGROUND_ONLY:
- setSummary(getEnterpriseString(BACKGROUND_ACCESS_ENABLED_BY_ADMIN_MESSAGE,
+ setSummary(Utils.getEnterpriseString(
+ getContext(),
+ BACKGROUND_ACCESS_ENABLED_BY_ADMIN_MESSAGE,
getResource(summary.getMsg())));
break;
case DISABLED_BY_ADMIN_BACKGROUND_ONLY:
- setSummary(getEnterpriseString(BACKGROUND_ACCESS_DISABLED_BY_ADMIN_MESSAGE,
+ setSummary(Utils.getEnterpriseString(
+ getContext(),
+ BACKGROUND_ACCESS_DISABLED_BY_ADMIN_MESSAGE,
getResource(summary.getMsg())));
break;
case ENABLED_BY_ADMIN_FOREGROUND_ONLY:
- setSummary(getEnterpriseString(FOREGROUND_ACCESS_ENABLED_BY_ADMIN_MESSAGE,
+ setSummary(Utils.getEnterpriseString(
+ getContext(),
+ FOREGROUND_ACCESS_ENABLED_BY_ADMIN_MESSAGE,
getResource(summary.getMsg())));
break;
default:
@@ -297,13 +300,6 @@ class PermissionPreference extends MultiTargetSwitchPreference {
}
}
- private String getEnterpriseString(String updatableStringId, int defaultStringId) {
- DevicePolicyManager dpm = getSystemServiceSafe(getContext(), DevicePolicyManager.class);
- return SdkLevel.isAtLeastT()
- ? dpm.getString(updatableStringId, () -> getContext().getString(defaultStringId))
- : getContext().getString(defaultStringId);
- }
-
int getResource(SummaryMessage summary) {
switch (summary) {
case DISABLED_BY_ADMIN:
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/SafetyCenterQsFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/SafetyCenterQsFragment.java
index 8d10dd52d..bee658d7a 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/SafetyCenterQsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/SafetyCenterQsFragment.java
@@ -24,6 +24,7 @@ import static com.android.permissioncontroller.Constants.EXTRA_SESSION_ID;
import static com.android.permissioncontroller.Constants.INVALID_SESSION_ID;
import android.content.Context;
+import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
@@ -44,6 +45,7 @@ import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
+import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
@@ -51,7 +53,7 @@ import androidx.transition.AutoTransition;
import androidx.transition.TransitionManager;
import com.android.permissioncontroller.R;
-import com.android.permissioncontroller.permission.ui.model.SafetyCenterViewModel;
+import com.android.permissioncontroller.permission.ui.model.SafetyCenterQsViewModel;
import com.android.permissioncontroller.permission.ui.model.SafetyCenterViewModelFactory;
import com.android.permissioncontroller.permission.utils.KotlinUtils;
import com.android.permissioncontroller.permission.utils.Utils;
@@ -73,7 +75,8 @@ public class SafetyCenterQsFragment extends Fragment {
private long mSessionId;
private List<PermissionGroupUsage> mPermGroupUsages;
- private SafetyCenterViewModel mViewModel;
+ private SafetyCenterQsViewModel mViewModel;
+ private View mRootView;
static {
sToggleButtons.put(CAMERA, R.id.camera_toggle);
@@ -116,12 +119,14 @@ public class SafetyCenterQsFragment extends Fragment {
SafetyCenterViewModelFactory factory = new SafetyCenterViewModelFactory(
getActivity().getApplication(), mSessionId, mPermGroupUsages);
- mViewModel = new ViewModelProvider(this, factory).get(SafetyCenterViewModel.class);
+ mViewModel = new ViewModelProvider(this, factory).get(SafetyCenterQsViewModel.class);
mViewModel.getSensorPrivacyLiveData()
.observe(this, (v) -> setSensorToggleState(v, getView()));
//LightAppPermGroupLiveDatas are kept track of in the view model,
// we need to start observing them here
- mViewModel.getLightAppPermGroupLiveData().observe(this, v -> {});
+ if (!mPermGroupUsages.isEmpty()) {
+ mViewModel.getPermDataLoadedLiveData().observe(this, this::onPermissionGroupsLoaded);
+ }
}
@Override
@@ -130,11 +135,24 @@ public class SafetyCenterQsFragment extends Fragment {
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.safety_center_qs, container, false);
root.findViewById(R.id.security_settings_button).setOnClickListener(
(v) -> mViewModel.navigateToSecuritySettings(this));
- setSensorToggleState(new ArrayMap<>(), root);
- addPermissionUsageInformation(root);
+ mRootView = root;
+ if (mPermGroupUsages.isEmpty()) {
+ mRootView.setVisibility(View.VISIBLE);
+ setSensorToggleState(new ArrayMap<>(), mRootView);
+ } else {
+ mRootView.setVisibility(View.GONE);
+ }
return root;
}
+ private void onPermissionGroupsLoaded(boolean initialized) {
+ if (initialized) {
+ mRootView.setVisibility(View.VISIBLE);
+ setSensorToggleState(new ArrayMap<>(), mRootView);
+ addPermissionUsageInformation(mRootView);
+ }
+ }
+
private void addPermissionUsageInformation(View rootView) {
if (rootView == null) {
return;
@@ -160,18 +178,35 @@ public class SafetyCenterQsFragment extends Fragment {
generateUsageLabel(usage), parentIconId, parentTitleId, parentLabelId,
parentButtonId);
+ if (usage.isPhoneCall()) {
+ ImageButton expandButton = permissionParent.findViewById(parentButtonId);
+ expandButton.setVisibility(View.GONE);
+ continue;
+ }
+
LinearLayout cardViewGroup = cardView.findViewById(R.id.full_card);
cardViewGroup.setId(View.generateViewId());
View expandedView = cardView.findViewById(R.id.expanded_view);
expandedView.setId(View.generateViewId());
+ boolean shouldAllowRevoke = mViewModel.shouldAllowRevoke(usage);
+ boolean isSubAttributionUsage = isSubAttributionUsage(usage.getAttributionLabel());
+ Intent manageServiceIntent = null;
+
+ if (isSubAttributionUsage) {
+ manageServiceIntent = mViewModel.getStartViewPermissionUsageIntent(getContext(),
+ usage);
+ }
+
+ boolean canHandleSubAttributionIntent = manageServiceIntent != null;
int managePermissionIconResId =
- usage.getAttributionTag() != null ? R.drawable.ic_setting
+ canHandleSubAttributionIntent || !shouldAllowRevoke ? R.drawable.ic_setting
: R.drawable.ic_block;
- int managePermissionLabelResId =
- usage.getAttributionTag() != null ? R.string.manage_service_qs
- : getRemovePermissionText(usage.getPermissionGroupName());
+
+ int managePermissionLabelResId = getManagePermissionLabel(canHandleSubAttributionIntent,
+ shouldAllowRevoke,
+ usage.getPermissionGroupName());
RelativeLayout manageParent = populateExpandedPermission(cardView,
R.id.manage_parent,
@@ -192,7 +227,7 @@ public class SafetyCenterQsFragment extends Fragment {
MaterialCardView managePermission = cardView.findViewById(R.id.manage_permission);
managePermission.setId(View.generateViewId());
- if (usage.getAttributionTag() == null) {
+ if (shouldAllowRevoke) {
managePermission.setOnClickListener(l -> {
permissionParent.callOnClick();
permissionParent.setOnClickListener(null);
@@ -202,9 +237,7 @@ public class SafetyCenterQsFragment extends Fragment {
revokePermission(permissionParent, parentIconId, parentLabelId, usage);
});
} else {
- managePermission.setOnClickListener(l -> {
- mViewModel.navigateToManageService(this, getContext(), usage);
- });
+ setManagePermissionClickListener(managePermission, usage, manageServiceIntent);
}
MaterialCardView seeUsage = cardView.findViewById(R.id.see_usage);
@@ -215,6 +248,52 @@ public class SafetyCenterQsFragment extends Fragment {
}
}
+ private void setManagePermissionClickListener(MaterialCardView managePermission,
+ PermissionGroupUsage usage, Intent manageServiceIntent) {
+ if (manageServiceIntent != null) {
+ managePermission.setOnClickListener(l -> {
+ mViewModel.navigateToManageService(this, manageServiceIntent);
+ });
+ } else {
+ managePermission.setOnClickListener(l -> {
+ mViewModel.navigateToManageAppPermissions(this, usage);
+ });
+ }
+
+ }
+
+ private int getManagePermissionLabel(boolean canHandleIntent,
+ boolean shouldAllowRevoke,
+ String permissionGroupName) {
+ if (canHandleIntent) {
+ return R.string.manage_service_qs;
+ }
+ if (!shouldAllowRevoke) {
+ return R.string.manage_permissions_qs;
+ }
+ return getRemovePermissionText(permissionGroupName);
+ }
+
+ private boolean isSubAttributionUsage(@Nullable CharSequence attributionLabel) {
+ if (attributionLabel == null || attributionLabel.length() == 0) {
+ return false;
+ }
+ return true;
+ }
+
+ private void revokePermission(RelativeLayout permissionParent, int iconId, int labelId,
+ PermissionGroupUsage usage) {
+ mViewModel.revokePermission(usage);
+ ImageView iconView = permissionParent.findViewById(iconId);
+ Drawable background = getContext().getDrawable(
+ R.drawable.indicator_background_circle).mutate();
+ background.setTint(getContext().getColor(R.color.safety_center_done));
+ Drawable icon = getContext().getDrawable(R.drawable.ic_check);
+ iconView.setImageDrawable(constructIcon(icon, background));
+ TextView labelView = permissionParent.findViewById(labelId);
+ labelView.setText(R.string.permissions_removed_qs);
+ }
+
private void setExpansionClickListener(View parentView, View expandedView,
LinearLayout cardViewGroup, RelativeLayout removeParent, RelativeLayout usageParent,
ImageButton expandButton) {
@@ -238,21 +317,6 @@ public class SafetyCenterQsFragment extends Fragment {
});
}
- private void revokePermission(RelativeLayout permissionParent, int iconId, int labelId,
- PermissionGroupUsage usage) {
-
- mViewModel.revokePermission(usage);
- ImageView iconView = permissionParent.findViewById(iconId);
- Drawable background = getContext().getDrawable(
- R.drawable.indicator_background_circle).mutate();
- background.setTint(getContext().getColor(R.color.safety_center_done));
- Drawable icon = getContext().getDrawable(R.drawable.ic_check);
- iconView.setImageDrawable(constructIcon(icon, background));
-
- TextView labelView = permissionParent.findViewById(labelId);
- labelView.setText(R.string.permissions_removed_qs);
- }
-
private String generateUsageLabel(PermissionGroupUsage usage) {
Context context = getContext();
@@ -315,6 +379,7 @@ public class SafetyCenterQsFragment extends Fragment {
TextView titleText = new TextView(getContext());
titleText.setId(titleId);
titleText.setText(permGroupLabel);
+ titleText.setContentDescription(permGroupLabel);
RelativeLayout.LayoutParams titleParams = new RelativeLayout.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
titleParams.setMargins(convertDpToPixel(10), 0, convertDpToPixel(4), convertDpToPixel(4));
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/SafetyCenterViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/SafetyCenterQsViewModel.kt
index f4500e262..7040379f4 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/SafetyCenterViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/SafetyCenterQsViewModel.kt
@@ -46,7 +46,7 @@ import com.android.permissioncontroller.permission.utils.LocationUtils
import kotlin.collections.set
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
-class SafetyCenterViewModel(
+class SafetyCenterQsViewModel(
private val app: Application,
private val sessionId: Long,
private val permGroupUsages: List<PermissionGroupUsage>
@@ -59,29 +59,51 @@ class SafetyCenterViewModel(
val lightAppPermMap = mutableMapOf<Triple<String, String, UserHandle>, LightAppPermGroup?>()
- val lightAppPermGroupLiveData = object
+ val permDataLoadedLiveData = object
: SmartUpdateMediatorLiveData<Boolean>() {
+ private val lightAppPermLiveDatas = mutableMapOf<Triple<String, String, UserHandle>,
+ LightAppPermGroupLiveData>()
+
init {
for (permGroupUsage in permGroupUsages) {
val pgTriple = Triple(permGroupUsage.packageName,
permGroupUsage.permissionGroupName,
UserHandle.getUserHandleForUid(permGroupUsage.uid))
val appPermGroupLiveData = LightAppPermGroupLiveData[pgTriple]
- addSource(appPermGroupLiveData) { v ->
- lightAppPermMap[pgTriple] = v
+ lightAppPermLiveDatas[pgTriple] = appPermGroupLiveData
+ addSource(appPermGroupLiveData) {
+ update()
}
}
}
override fun onUpdate() {
- // Do nothing
+ if (!lightAppPermLiveDatas.all { it.value.isInitialized }) {
+ return
+ }
+ for ((pgTriple, lightAppPermLiveData) in lightAppPermLiveDatas) {
+ lightAppPermMap[pgTriple] = lightAppPermLiveData.value
+ }
+ value = true
}
}
+ fun shouldAllowRevoke(usage: PermissionGroupUsage): Boolean {
+ val pgTriple = Triple(usage.packageName,
+ usage.permissionGroupName,
+ UserHandle.getUserHandleForUid(usage.uid))
+ val group = lightAppPermMap[pgTriple] ?: return false
+ return group.supportsRuntimePerms &&
+ !group.hasInstallToRuntimeSplit &&
+ !group.isBackgroundFixed &&
+ !group.isForegroundFixed &&
+ !group.isGrantedByDefault
+ }
+
fun revokePermission(usage: PermissionGroupUsage) {
val group = lightAppPermMap.get(Triple(usage.packageName, usage.permissionGroupName,
- UserHandle.getUserHandleForUid(usage.uid)))
+ UserHandle.getUserHandleForUid(usage.uid))) ?: return
if (group != null) {
KotlinUtils.revokeForegroundRuntimePermissions(app, group)
@@ -148,22 +170,39 @@ class SafetyCenterViewModel(
}
}
- fun navigateToManageService(fragment: Fragment, context: Context, usage: PermissionGroupUsage) {
+ fun navigateToManageService(fragment: Fragment, navigationIntent: Intent) {
+ fragment.startActivity(navigationIntent)
+ }
+
+ fun navigateToManageAppPermissions(fragment: Fragment, usage: PermissionGroupUsage) {
+ fragment.startActivity(getDefaultManageAppPermissionsIntent(usage.packageName, usage.uid))
+ }
+
+ fun getStartViewPermissionUsageIntent(context: Context, usage: PermissionGroupUsage):
+ Intent? {
var intent: Intent = Intent(Intent.ACTION_MANAGE_PERMISSION_USAGE)
intent.setPackage(usage.packageName)
intent.putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, usage.permissionGroupName)
intent.putExtra(Intent.EXTRA_ATTRIBUTION_TAGS, arrayOf(usage.attributionTag.toString()))
intent.putExtra(Intent.EXTRA_SHOWING_ATTRIBUTION, true)
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
val resolveInfo: ResolveInfo? = context.packageManager.resolveActivity(
intent, PackageManager.ResolveInfoFlags.of(0))
- if (resolveInfo?.activityInfo == null) {
- intent = Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS)
- intent.putExtra(Intent.EXTRA_USER, UserHandle.getUserHandleForUid(usage.uid))
- intent.putExtra(Intent.EXTRA_PACKAGE_NAME, usage.packageName)
- } else {
+ if (resolveInfo != null && resolveInfo.activityInfo != null &&
+ resolveInfo.activityInfo.permission ==
+ android.Manifest.permission.START_VIEW_PERMISSION_USAGE) {
intent.component = ComponentName(usage.packageName, resolveInfo.activityInfo.name)
+ return intent
}
- fragment.startActivity(intent)
+ return null
+ }
+
+ private fun getDefaultManageAppPermissionsIntent(packageName: String, uid: Int): Intent {
+ val intent = Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS)
+ intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName)
+ intent.putExtra(Intent.EXTRA_USER, UserHandle.getUserHandleForUid(uid))
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ return intent
}
fun navigateToSeeUsage(fragment: Fragment, permGroupName: String) {
@@ -174,7 +213,7 @@ class SafetyCenterViewModel(
}
/**
- * Factory for a SafetyCenterViewModel
+ * Factory for a SafetyCenterQsViewModel
*
* @param app The current application
* @param sessionId A session ID used in logs to identify this particular session
@@ -187,6 +226,6 @@ class SafetyCenterViewModelFactory(
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@Suppress("UNCHECKED_CAST")
- return SafetyCenterViewModel(app, sessionId, permGroupUsages) as T
+ return SafetyCenterQsViewModel(app, sessionId, permGroupUsages) as T
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
index dc8f032c1..332963aaa 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
@@ -43,6 +43,8 @@ import android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE
import android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE
import android.content.pm.PermissionGroupInfo
import android.content.pm.PermissionInfo
+import android.graphics.Bitmap
+import android.graphics.Canvas
import android.graphics.drawable.Drawable
import android.os.Build
import android.os.Bundle
@@ -337,6 +339,16 @@ object KotlinUtils {
}
}
+ fun convertToBitmap(pkgIcon: Drawable): Bitmap {
+ val pkgIconBmp = Bitmap.createBitmap(pkgIcon.intrinsicWidth, pkgIcon.intrinsicHeight,
+ Bitmap.Config.ARGB_8888)
+ // Draw the icon so it can be displayed.
+ val canvas = Canvas(pkgIconBmp)
+ pkgIcon.setBounds(0, 0, pkgIcon.intrinsicWidth, pkgIcon.intrinsicHeight)
+ pkgIcon.draw(canvas)
+ return pkgIconBmp
+ }
+
/**
* Gets a package's uid, using a cached liveData value, if the liveData is currently being
* observed (and thus has an up-to-date value).
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java b/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java
index e3715f74b..46a068621 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java
@@ -49,6 +49,7 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.Manifest;
import android.app.AppOpsManager;
import android.app.Application;
+import android.app.admin.DevicePolicyManager;
import android.app.role.RoleManager;
import android.content.ActivityNotFoundException;
import android.content.Context;
@@ -1385,7 +1386,6 @@ public final class Utils {
*/
public static void navigateToNotificationSettings(@NonNull Context context) {
Intent notificationIntent = new Intent(Settings.ACTION_ALL_APPS_NOTIFICATION_SETTINGS);
- notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(notificationIntent);
}
@@ -1400,7 +1400,6 @@ public final class Utils {
@NonNull String packageName, @NonNull UserHandle user) {
Intent notificationIntent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
notificationIntent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName);
- notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivityAsUser(notificationIntent, user);
}
@@ -1449,4 +1448,25 @@ public final class Utils {
|| Manifest.permission_group.CAMERA.equals(groupName)
|| Manifest.permission_group.MICROPHONE.equals(groupName);
}
+
+ /**
+ * Returns the appropriate enterprise string for the provided IDs
+ */
+ @NonNull
+ public static String getEnterpriseString(@NonNull Context context,
+ @NonNull String updatableStringId, int defaultStringId, @NonNull Object... formatArgs) {
+ return SdkLevel.isAtLeastT()
+ ? getUpdatableEnterpriseString(
+ context, updatableStringId, defaultStringId, formatArgs)
+ : context.getString(defaultStringId, formatArgs);
+ }
+
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ @NonNull
+ private static String getUpdatableEnterpriseString(@NonNull Context context,
+ @NonNull String updatableStringId, int defaultStringId, @NonNull Object... formatArgs) {
+ DevicePolicyManager dpm = getSystemServiceSafe(context, DevicePolicyManager.class);
+ return dpm.getResources().getString(updatableStringId, () -> context.getString(
+ defaultStringId, formatArgs), formatArgs);
+ }
}
diff --git a/PermissionController/src/com/android/permissioncontroller/privacysources/PrivacySource.kt b/PermissionController/src/com/android/permissioncontroller/privacysources/PrivacySource.kt
new file mode 100644
index 000000000..700f0f4b9
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/privacysources/PrivacySource.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.permissioncontroller.privacysources
+
+import android.content.Context
+import android.content.Intent
+
+interface PrivacySource {
+
+ /**
+ * Indicates that permission controller has received the safety center enabled changed broadcast
+ *
+ * <p> Invoked when {@link SafetyCenterManager.ACTION_SAFETY_CENTER_ENABLED_CHANGED} received
+ *
+ * @param enabled: {@code true} if Safety Center now enabled
+ */
+ fun safetyCenterEnabledChanged(enabled: Boolean)
+
+ /** Indicates that permission controller has received the safety center rescan broadcast.
+ * context: Context of the broadcast
+ * intent: Intent of the broadcast
+ * refreshEvent: Enum explaining why this rescan was triggered. If the value is
+ * EVENT_REFRESH_REQUESTED, get the broadcast id using code below,
+ * val refreshBroadcastId = intent.getStringExtra(SafetyCenterManager
+ * .EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID)
+ * and add it to the safety event, when sending SafetyCenterManager#setSafetyCenterUpdate
+ * val safetyEvent = SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
+ * .setRefreshBroadcastId(refreshBroadcastId).build()
+ */
+ fun rescanAndPushSafetyCenterData(
+ context: Context,
+ intent: Intent,
+ refreshEvent: SafetyCenterReceiver.RefreshEvent
+ )
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/privacysources/SafetyCenterReceiver.kt b/PermissionController/src/com/android/permissioncontroller/privacysources/SafetyCenterReceiver.kt
new file mode 100644
index 000000000..a793ebaee
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/privacysources/SafetyCenterReceiver.kt
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.permissioncontroller.privacysources
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.Intent.ACTION_BOOT_COMPLETED
+import android.safetycenter.SafetyCenterManager
+import android.safetycenter.SafetyCenterManager.ACTION_REFRESH_SAFETY_SOURCES
+import android.safetycenter.SafetyCenterManager.ACTION_SAFETY_CENTER_ENABLED_CHANGED
+import android.safetycenter.SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCE_IDS
+import com.android.modules.utils.build.SdkLevel
+import com.android.permissioncontroller.PermissionControllerApplication
+import com.android.permissioncontroller.permission.utils.Utils
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers.Default
+import kotlinx.coroutines.launch
+
+private fun createMapOfSourceIdsToSources(): Map<String, PrivacySource> = emptyMap()
+
+class SafetyCenterReceiver(
+ private val getMapOfSourceIdsToSources: () -> Map<String, PrivacySource> =
+ ::createMapOfSourceIdsToSources,
+ private val dispatcher: CoroutineDispatcher = Default
+) : BroadcastReceiver() {
+
+ enum class RefreshEvent {
+ UNKNOWN,
+ EVENT_DEVICE_REBOOTED,
+ EVENT_REFRESH_REQUESTED
+ }
+
+ override fun onReceive(context: Context, intent: Intent) {
+ if (!SdkLevel.isAtLeastT()) {
+ return
+ }
+ val safetyCenterManager: SafetyCenterManager = Utils.getSystemServiceSafe(
+ PermissionControllerApplication.get().applicationContext,
+ SafetyCenterManager::class.java
+ )
+
+ if (!safetyCenterManager.isSafetyCenterEnabled &&
+ intent.action != ACTION_SAFETY_CENTER_ENABLED_CHANGED) {
+ return
+ }
+
+ val mapOfSourceIdsToSources = getMapOfSourceIdsToSources()
+
+ when (intent.action) {
+ ACTION_SAFETY_CENTER_ENABLED_CHANGED -> {
+ safetyCenterEnabledChanged(
+ safetyCenterManager.isSafetyCenterEnabled,
+ mapOfSourceIdsToSources.values)
+ }
+ ACTION_REFRESH_SAFETY_SOURCES -> {
+ val sourceIdsExtra = intent.getStringArrayExtra(EXTRA_REFRESH_SAFETY_SOURCE_IDS)
+ if (sourceIdsExtra != null && sourceIdsExtra.isNotEmpty()) {
+ refreshSafetySources(
+ context,
+ intent,
+ RefreshEvent.EVENT_REFRESH_REQUESTED,
+ mapOfSourceIdsToSources,
+ sourceIdsExtra.toList()
+ )
+ }
+ }
+ ACTION_BOOT_COMPLETED -> {
+ refreshSafetySources(
+ context,
+ intent,
+ RefreshEvent.EVENT_DEVICE_REBOOTED,
+ mapOfSourceIdsToSources,
+ mapOfSourceIdsToSources.keys.toList()
+ )
+ }
+ }
+ }
+
+ private fun safetyCenterEnabledChanged(
+ enabled: Boolean,
+ privacySources: Collection<PrivacySource>
+ ) {
+ privacySources.forEach { source ->
+ CoroutineScope(dispatcher).launch {
+ source.safetyCenterEnabledChanged(enabled)
+ }
+ }
+ }
+
+ private fun refreshSafetySources(
+ context: Context,
+ intent: Intent,
+ refreshEvent: RefreshEvent,
+ mapOfSourceIdsToSources: Map<String, PrivacySource>,
+ sourceIdsToRefresh: List<String>
+ ) {
+ for (sourceId in sourceIdsToRefresh) {
+ CoroutineScope(dispatcher).launch {
+ mapOfSourceIdsToSources[sourceId]?.rescanAndPushSafetyCenterData(context, intent,
+ refreshEvent)
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/privacysources/package-info.java b/PermissionController/src/com/android/permissioncontroller/privacysources/package-info.java
new file mode 100644
index 000000000..360912eb8
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/privacysources/package-info.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@androidx.annotation.RequiresApi(api = android.os.Build.VERSION_CODES.TIRAMISU)
+package com.android.permissioncontroller.privacysources;
diff --git a/PermissionController/src/com/android/permissioncontroller/role/model/DevicePolicyManagementRoleBehavior.java b/PermissionController/src/com/android/permissioncontroller/role/model/DevicePolicyManagementRoleBehavior.java
new file mode 100644
index 000000000..8232847e0
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/role/model/DevicePolicyManagementRoleBehavior.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.permissioncontroller.role.model;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.os.Build;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+/**
+ * Class for behavior of the device policy management role.
+ */
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+public class DevicePolicyManagementRoleBehavior implements RoleBehavior {
+
+ @Override
+ public Boolean shouldAllowBypassingQualification(@NonNull Role role,
+ @NonNull Context context) {
+ DevicePolicyManager devicePolicyManager =
+ context.getSystemService(DevicePolicyManager.class);
+ return devicePolicyManager.shouldAllowBypassingDevicePolicyManagementRoleQualification();
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/model/HomeRoleBehavior.java b/PermissionController/src/com/android/permissioncontroller/role/model/HomeRoleBehavior.java
index f10b80467..af6acfeec 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/model/HomeRoleBehavior.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/model/HomeRoleBehavior.java
@@ -16,8 +16,7 @@
package com.android.permissioncontroller.role.model;
-import android.app.admin.DevicePolicyManager;
-import android.app.admin.DevicePolicyResources.Strings.PermissionController;
+import android.app.admin.DevicePolicyResources.Strings.DefaultAppSettings;
import android.app.role.RoleManager;
import android.content.ActivityNotFoundException;
import android.content.Context;
@@ -35,9 +34,9 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.Preference;
-import com.android.modules.utils.build.SdkLevel;
import com.android.permissioncontroller.R;
import com.android.permissioncontroller.permission.utils.CollectionUtils;
+import com.android.permissioncontroller.permission.utils.Utils;
import com.android.permissioncontroller.role.ui.TwoTargetPreference;
import com.android.permissioncontroller.role.utils.UserUtils;
@@ -149,19 +148,9 @@ public class HomeRoleBehavior implements RoleBehavior {
@NonNull UserHandle user, @NonNull Context context) {
boolean missingWorkProfileSupport = isMissingWorkProfileSupport(applicationInfo, context);
preference.setEnabled(!missingWorkProfileSupport);
- preference.setSummary(
- missingWorkProfileSupport ? getMissingWorkProfileSupportSummary(context) : null);
- }
-
- @NonNull
- private String getMissingWorkProfileSupportSummary(@NonNull Context context) {
- DevicePolicyManager devicePolicyManager = context.getSystemService(
- DevicePolicyManager.class);
- return SdkLevel.isAtLeastT()
- ? devicePolicyManager.getString(
- PermissionController.HOME_MISSING_WORK_PROFILE_SUPPORT_MESSAGE,
- () -> context.getString(R.string.home_missing_work_profile_support))
- : context.getString(R.string.home_missing_work_profile_support);
+ preference.setSummary(missingWorkProfileSupport ? Utils.getEnterpriseString(context,
+ DefaultAppSettings.HOME_MISSING_WORK_PROFILE_SUPPORT_MESSAGE,
+ R.string.home_missing_work_profile_support) : null);
}
private boolean isMissingWorkProfileSupport(@NonNull ApplicationInfo applicationInfo,
diff --git a/PermissionController/src/com/android/permissioncontroller/role/model/Role.java b/PermissionController/src/com/android/permissioncontroller/role/model/Role.java
index 8f8b845cb..3f68a5de4 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/model/Role.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/model/Role.java
@@ -259,13 +259,6 @@ public class Role {
return mName;
}
- /**
- * @see #mAllowBypassingQualification
- */
- public boolean shouldAllowBypassingQualification() {
- return mAllowBypassingQualification;
- }
-
@Nullable
public RoleBehavior getBehavior() {
return mBehavior;
@@ -637,6 +630,24 @@ public class Role {
}
/**
+ * Check whether this role is allowed to bypass qualification, if enabled globally.
+ *
+ * @param context the {@code Context} to retrieve system services
+ *
+ * @return whether this role is allowed to bypass qualification
+ */
+ public boolean shouldAllowBypassingQualification(@NonNull Context context) {
+ if (mBehavior != null) {
+ Boolean allowBypassingQualification = mBehavior.shouldAllowBypassingQualification(this,
+ context);
+ if (allowBypassingQualification != null) {
+ return allowBypassingQualification;
+ }
+ }
+ return mAllowBypassingQualification;
+ }
+
+ /**
* Check whether a package is qualified for this role, i.e. whether it contains all the required
* components (plus meeting some other general restrictions).
*
@@ -647,7 +658,7 @@ public class Role {
*/
public boolean isPackageQualified(@NonNull String packageName, @NonNull Context context) {
RoleManager roleManager = context.getSystemService(RoleManager.class);
- if (mAllowBypassingQualification
+ if (shouldAllowBypassingQualification(context)
&& RoleManagerCompat.isBypassingRoleQualification(roleManager)) {
return true;
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/model/RoleBehavior.java b/PermissionController/src/com/android/permissioncontroller/role/model/RoleBehavior.java
index 7b1a501e7..e5402c2ed 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/model/RoleBehavior.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/model/RoleBehavior.java
@@ -115,11 +115,11 @@ public interface RoleBehavior {
}
/**
- * @see Role#getQualifyingPackagesAsUser(UserHandle, Context)
+ * @see Role#shouldAllowBypassingQualification(Context)
*/
@Nullable
- default List<String> getQualifyingPackagesAsUser(@NonNull Role role, @NonNull UserHandle user,
- @NonNull Context context) {
+ default Boolean shouldAllowBypassingQualification(@NonNull Role role,
+ @NonNull Context context) {
return null;
}
@@ -133,6 +133,15 @@ public interface RoleBehavior {
}
/**
+ * @see Role#getQualifyingPackagesAsUser(UserHandle, Context)
+ */
+ @Nullable
+ default List<String> getQualifyingPackagesAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {
+ return null;
+ }
+
+ /**
* @see Role#grant(String, boolean, boolean, boolean, Context)
*/
default void grant(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java
index b1cadf50d..752dfb9cc 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java
@@ -16,8 +16,7 @@
package com.android.permissioncontroller.role.ui;
-import android.app.admin.DevicePolicyManager;
-import android.app.admin.DevicePolicyResources.Strings.PermissionController;
+import android.app.admin.DevicePolicyResources.Strings.DefaultAppSettings;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -39,7 +38,6 @@ import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
-import com.android.modules.utils.build.SdkLevel;
import com.android.permissioncontroller.R;
import com.android.permissioncontroller.permission.utils.Utils;
import com.android.permissioncontroller.role.model.Role;
@@ -135,7 +133,9 @@ public class DefaultAppListChildFragment<PF extends PreferenceFragmentCompat
if (workPreferenceCategory == null) {
workPreferenceCategory = new PreferenceCategory(context);
workPreferenceCategory.setKey(PREFERENCE_KEY_WORK_CATEGORY);
- workPreferenceCategory.setTitle(getDefaultAppsForWorkTitle(context));
+ workPreferenceCategory.setTitle(Utils.getEnterpriseString(context,
+ DefaultAppSettings.WORK_PROFILE_DEFAULT_APPS_TITLE,
+ R.string.default_apps_for_work));
}
preferenceScreen.addPreference(workPreferenceCategory);
addPreferences(workPreferenceCategory, workRoleItems, oldWorkPreferences, this,
@@ -145,19 +145,6 @@ public class DefaultAppListChildFragment<PF extends PreferenceFragmentCompat
preferenceFragment.onPreferenceScreenChanged();
}
- @NonNull
- private String getDefaultAppsForWorkTitle(@NonNull Context context) {
- if (SdkLevel.isAtLeastT()) {
- DevicePolicyManager devicePolicyManager = context.getSystemService(
- DevicePolicyManager.class);
- return devicePolicyManager.getString(
- PermissionController.WORK_PROFILE_DEFAULT_APPS_TITLE,
- () -> context.getString(R.string.default_apps_for_work));
- } else {
- return context.getString(R.string.default_apps_for_work);
- }
- }
-
private static void clearPreferences(@NonNull PreferenceGroup preferenceGroup,
@NonNull ArrayMap<String, Preference> oldPreferences) {
for (int i = preferenceGroup.getPreferenceCount() - 1; i >= 0; --i) {
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/OWNERS b/PermissionController/src/com/android/permissioncontroller/safetycenter/OWNERS
new file mode 100644
index 000000000..72fe70201
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/OWNERS
@@ -0,0 +1 @@
+include /SafetyCenter/OWNERS
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterDashboardFragment.java b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterDashboardFragment.java
index 86865dcd7..443a56ac5 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterDashboardFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterDashboardFragment.java
@@ -60,17 +60,21 @@ public final class SafetyCenterDashboardFragment extends PreferenceFragmentCompa
new OnSafetyCenterDataChangedListener() {
@Override
public void onSafetyCenterDataChanged(@NonNull SafetyCenterData data) {
- Log.i(TAG, String.format(
- "onSafetyCenterDataChanged called with: %s", data.toString()));
+ Log.i(TAG, String.format("onSafetyCenterDataChanged called with: %s", data));
+
+ Context context = getContext();
+ if (context == null) {
+ return;
+ }
mSafetyStatusPreference.setSafetyStatus(data.getStatus());
// TODO(b/208212820): Only update entries that have changed since last
// update, rather than deleting and re-adding all.
- updateIssues(data.getIssues());
- updateSafetyEntries(data.getEntriesOrGroups());
- updateStaticSafetyEntries(data.getStaticEntryGroups());
+ updateIssues(context, data.getIssues());
+ updateSafetyEntries(context, data.getEntriesOrGroups());
+ updateStaticSafetyEntries(context, data.getStaticEntryGroups());
}
};
@@ -85,10 +89,8 @@ public final class SafetyCenterDashboardFragment extends PreferenceFragmentCompa
mSafetyStatusPreference = requireNonNull(
getPreferenceScreen().findPreference(SAFETY_STATUS_KEY));
// TODO: Use real strings here, or set more sensible defaults in the layout
- mSafetyStatusPreference.setSafetyStatus(new SafetyCenterStatus.Builder()
+ mSafetyStatusPreference.setSafetyStatus(new SafetyCenterStatus.Builder("Looks good", "")
.setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_UNKNOWN)
- .setTitle("Looks good")
- .setSummary("")
.build());
mSafetyStatusPreference.setRescanButtonOnClickListener(unused ->
mSafetyCenterManager.refreshSafetySources(
@@ -97,29 +99,35 @@ public final class SafetyCenterDashboardFragment extends PreferenceFragmentCompa
mIssuesGroup = getPreferenceScreen().findPreference(ISSUES_GROUP_KEY);
mEntriesGroup = getPreferenceScreen().findPreference(ENTRIES_GROUP_KEY);
mStaticEntriesGroup = getPreferenceScreen().findPreference(STATIC_ENTRIES_GROUP_KEY);
+ }
+ @Override
+ public void onResume() {
+ super.onResume();
mSafetyCenterManager.addOnSafetyCenterDataChangedListener(
- ContextCompat.getMainExecutor(context), mOnSafetyCenterDataChangedListener);
+ ContextCompat.getMainExecutor(requireNonNull(getContext())),
+ mOnSafetyCenterDataChangedListener);
mSafetyCenterManager.refreshSafetySources(SafetyCenterManager.REFRESH_REASON_PAGE_OPEN);
}
@Override
- public void onDestroyView() {
- super.onDestroyView();
+ public void onPause() {
mSafetyCenterManager.removeOnSafetyCenterDataChangedListener(
mOnSafetyCenterDataChangedListener);
+ super.onPause();
}
- private void updateIssues(List<SafetyCenterIssue> issues) {
+ private void updateIssues(Context context, List<SafetyCenterIssue> issues) {
mIssuesGroup.removeAll();
issues.stream()
- .map(issue -> new IssueCardPreference(getContext(), issue))
+ .map(issue -> new IssueCardPreference(context, issue))
.forEachOrdered(mIssuesGroup::addPreference);
}
// TODO(b/208212820): Add groups and move to separate controller
- private void updateSafetyEntries(List<SafetyCenterEntryOrGroup> entriesOrGroups) {
+ private void updateSafetyEntries(Context context,
+ List<SafetyCenterEntryOrGroup> entriesOrGroups) {
mEntriesGroup.removeAll();
entriesOrGroups.stream()
@@ -127,16 +135,17 @@ public final class SafetyCenterDashboardFragment extends PreferenceFragmentCompa
entryOrGroup.getEntry() != null
? Stream.of(entryOrGroup.getEntry())
: entryOrGroup.getEntryGroup().getEntries().stream())
- .map(entry -> new SafetyEntryPreference(getContext(), entry))
+ .map(entry -> new SafetyEntryPreference(context, entry))
.forEachOrdered(mEntriesGroup::addPreference);
}
- private void updateStaticSafetyEntries(List<SafetyCenterStaticEntryGroup> staticEntryGroups) {
+ private void updateStaticSafetyEntries(Context context,
+ List<SafetyCenterStaticEntryGroup> staticEntryGroups) {
mStaticEntriesGroup.removeAll();
staticEntryGroups.stream()
.flatMap(group -> group.getStaticEntries().stream())
- .map(entry -> new StaticSafetyEntryPreference(getContext(), entry))
+ .map(entry -> new StaticSafetyEntryPreference(context, entry))
.forEachOrdered(mStaticEntriesGroup::addPreference);
}
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyEntryPreference.java b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyEntryPreference.java
index bdedc46f2..e7751af4e 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyEntryPreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyEntryPreference.java
@@ -32,15 +32,18 @@ public class SafetyEntryPreference extends Preference {
setTitle(entry.getTitle());
setSummary(entry.getSummary());
setIcon(toSeverityLevel(entry.getSeverityLevel()).getEntryIconResId());
- setOnPreferenceClickListener(unused -> {
- try {
- entry.getPendingIntent().send();
- } catch (Exception ex) {
- Log.e(TAG, String.format("Failed to execute pending intent for entry: %s", entry),
- ex);
- }
- return true;
- });
+ if (entry.getPendingIntent() != null) {
+ setOnPreferenceClickListener(unused -> {
+ try {
+ entry.getPendingIntent().send();
+ } catch (Exception ex) {
+ Log.e(TAG,
+ String.format("Failed to execute pending intent for entry: %s", entry),
+ ex);
+ }
+ return true;
+ });
+ }
}
private static SeverityLevel toSeverityLevel(int entrySeverityLevel) {
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/StaticSafetyEntryPreference.java b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/StaticSafetyEntryPreference.java
index 8dcd4a44e..6b076ffaa 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/StaticSafetyEntryPreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/StaticSafetyEntryPreference.java
@@ -31,16 +31,18 @@ public class StaticSafetyEntryPreference extends Preference {
super(context);
setTitle(entry.getTitle());
setSummary(entry.getSummary());
- setOnPreferenceClickListener(unused -> {
- try {
- entry.getPendingIntent().send();
- } catch (Exception ex) {
- Log.e(TAG,
- String.format(
- "Failed to execute pending intent for static entry: %s", entry),
- ex);
- }
- return true;
- });
+ if (entry.getPendingIntent() != null) {
+ setOnPreferenceClickListener(unused -> {
+ try {
+ entry.getPendingIntent().send();
+ } catch (Exception ex) {
+ Log.e(TAG,
+ String.format(
+ "Failed to execute pending intent for static entry: %s", entry),
+ ex);
+ }
+ return true;
+ });
+ }
}
}
diff --git a/PermissionController/tests/mocking/Android.bp b/PermissionController/tests/mocking/Android.bp
index 2db167b71..42b3ceffb 100644
--- a/PermissionController/tests/mocking/Android.bp
+++ b/PermissionController/tests/mocking/Android.bp
@@ -108,6 +108,7 @@ android_test {
"androidx.test.rules",
"androidx.test.ext.truth",
"androidx.test.ext.junit",
+ "kotlinx_coroutines_test",
"mockito-target-extended-minus-junit4",
],
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/auto/DrivingDecisionReminderServiceTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/auto/DrivingDecisionReminderServiceTest.kt
deleted file mode 100644
index a4b17acb6..000000000
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/auto/DrivingDecisionReminderServiceTest.kt
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.permissioncontroller.auto
-
-import android.Manifest
-import android.app.Service.START_NOT_STICKY
-import android.app.Service.START_STICKY
-import android.car.Car
-import android.car.drivingstate.CarUxRestrictions
-import android.car.drivingstate.CarUxRestrictions.UX_RESTRICTIONS_BASELINE
-import android.car.drivingstate.CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED
-import android.car.drivingstate.CarUxRestrictionsManager
-import android.content.Context
-import android.content.Intent
-import android.content.pm.PackageManager
-import android.os.UserHandle
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.dx.mockito.inline.extended.ExtendedMockito
-import com.android.permissioncontroller.Constants
-import com.android.permissioncontroller.PermissionControllerApplication
-import com.google.common.truth.Truth.assertThat
-import org.junit.After
-import org.junit.Assume.assumeTrue
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentCaptor
-import org.mockito.ArgumentMatchers.eq
-import org.mockito.Captor
-import org.mockito.Mock
-import org.mockito.Mockito
-import org.mockito.Mockito.`when`
-import org.mockito.Mockito.any
-import org.mockito.Mockito.anyLong
-import org.mockito.Mockito.doNothing
-import org.mockito.Mockito.doReturn
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
-import org.mockito.MockitoSession
-import org.mockito.quality.Strictness
-import java.io.File
-
-@RunWith(AndroidJUnit4::class)
-class DrivingDecisionReminderServiceTest {
-
- companion object {
- val application = Mockito.mock(PermissionControllerApplication::class.java)
- const val TEST_PACKAGE_1 = "com.package.test1"
- const val TEST_PACKAGE_1_LABEL = "App1"
- const val TEST_PACKAGE_2 = "com.package.test2"
- const val TEST_PACKAGE_2_LABEL = "App2"
- const val TEST_PACKAGE_3 = "com.package.test3"
- const val TEST_PACKAGE_3_LABEL = "App3"
- const val LOCATION_PERMISSION_GROUP = Manifest.permission_group.LOCATION
- const val MICROPHONE_PERMISSION_GROUP = Manifest.permission_group.MICROPHONE
- const val CALENDAR_PERMISSION_GROUP = Manifest.permission_group.CALENDAR
- }
-
- @Mock
- lateinit var userHandle: UserHandle
-
- @Mock
- lateinit var car: Car
-
- @Mock
- lateinit var carUxRestrictionsManager: CarUxRestrictionsManager
-
- @Captor
- var uxRestrictionsChangedListener:
- ArgumentCaptor<CarUxRestrictionsManager.OnUxRestrictionsChangedListener>? = null
-
- @Captor
- var carServiceLifecycleListener: ArgumentCaptor<Car.CarServiceLifecycleListener>? = null
-
- private val noRestrictions = CarUxRestrictions.Builder(/* reqOpt= */ false,
- UX_RESTRICTIONS_BASELINE, System.currentTimeMillis()).build()
- private val fullRestrictions = CarUxRestrictions.Builder(/* reqOpt= */ true,
- UX_RESTRICTIONS_FULLY_RESTRICTED, System.currentTimeMillis()).build()
-
- private lateinit var mockitoSession: MockitoSession
- private lateinit var filesDir: File
- private lateinit var reminderService: DrivingDecisionReminderService
- private lateinit var testIntent: Intent
-
- @Before
- fun setup() {
- MockitoAnnotations.initMocks(this)
- mockitoSession = ExtendedMockito.mockitoSession()
- .mockStatic(PermissionControllerApplication::class.java)
- .mockStatic(Car::class.java)
- .strictness(Strictness.LENIENT).startMocking()
- `when`(PermissionControllerApplication.get()).thenReturn(application)
- filesDir = InstrumentationRegistry.getInstrumentation().getTargetContext().getCacheDir()
- `when`(application.filesDir).thenReturn(filesDir)
- `when`(car.getCarManager(eq(Car.CAR_UX_RESTRICTION_SERVICE)))
- .thenReturn(carUxRestrictionsManager)
- testIntent = createIntent(TEST_PACKAGE_1, LOCATION_PERMISSION_GROUP)
- reminderService = Mockito.spy(DrivingDecisionReminderService())
- doNothing().`when`(reminderService).showRecentGrantDecisionsPostDriveNotification()
- doReturn(InstrumentationRegistry.getInstrumentation().getTargetContext().resources)
- .`when`(reminderService).resources
- doReturn(ApplicationProvider.getApplicationContext()).`when`(reminderService)
- .applicationContext
-
- doReturn(TEST_PACKAGE_1_LABEL).`when`(reminderService)
- .getLabelForPackage(TEST_PACKAGE_1, userHandle)
- doReturn(TEST_PACKAGE_2_LABEL).`when`(reminderService)
- .getLabelForPackage(TEST_PACKAGE_2, userHandle)
- doReturn(TEST_PACKAGE_3_LABEL).`when`(reminderService)
- .getLabelForPackage(TEST_PACKAGE_3, userHandle)
-
- // TODO(b/209026677) - move this to @BeforeClass
- // only run tests on Auto. Placed after all lateinit variables have been created
- assumeTrue(isAutomotiveDevice())
- }
-
- private fun createIntent(packageName: String, permissionGroup: String): Intent {
- return DrivingDecisionReminderService.createIntent(
- ApplicationProvider.getApplicationContext(),
- packageName,
- permissionGroup,
- userHandle)
- }
-
- private fun isAutomotiveDevice(): Boolean {
- return InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageManager()
- .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
- }
-
- @After
- fun finish() {
- mockitoSession.finishMocking()
- val logFile = File(filesDir, Constants.LOGS_TO_DUMP_FILE)
- logFile.delete()
- }
-
- @Test
- fun createIntent_success() {
- assertThat(testIntent.getStringExtra(DrivingDecisionReminderService.EXTRA_PACKAGE_NAME))
- .isEqualTo(TEST_PACKAGE_1)
- assertThat(testIntent.getStringExtra(DrivingDecisionReminderService.EXTRA_PERMISSION_GROUP))
- .isEqualTo(LOCATION_PERMISSION_GROUP)
- assertThat(testIntent
- .getParcelableExtra<UserHandle>(DrivingDecisionReminderService.EXTRA_USER))
- .isEqualTo(userHandle)
- }
-
- @Test
- fun onStartCommand_invalidIntent_startNotSticky() {
- val result = reminderService.onStartCommand(null, /* flags= */ 0, /* startId= */ 0)
- assertThat(result).isEqualTo(START_NOT_STICKY)
- ExtendedMockito.verify({
- Car.createCar(any(Context::class.java), any(),
- anyLong(), any(Car.CarServiceLifecycleListener::class.java))
- }, never())
- }
-
- @Test
- fun onStartCommand_validIntent_startSticky() {
- val result = reminderService.onStartCommand(testIntent, /* flags= */ 0, /* startId= */ 0)
- assertThat(result).isEqualTo(START_STICKY)
- }
-
- @Test
- fun onStartCommand_multipleStarts_onlyCreatesCarOnce() {
- reminderService.onStartCommand(testIntent, /* flags= */ 0, /* startId= */ 0)
- val result = reminderService.onStartCommand(testIntent, /* flags= */ 0, /* startId= */ 0)
- assertThat(result).isEqualTo(START_STICKY)
-
- captureCreateCarLifecycleListener()
- }
-
- @Test
- fun onStartCommand_carNotReady_stopsSelf() {
- reminderService.onStartCommand(testIntent, /* flags= */ 0, /* startId= */ 0)
- captureCreateCarLifecycleListener()
-
- carServiceLifecycleListener?.value?.onLifecycleChanged(car, /* ready= */ false)
-
- verify(reminderService).stopSelf()
- }
-
- @Test
- fun onCarReady_registersRestrictionListener_restrictionChangeToUnrestricted_showNotification() {
- reminderService.onStartCommand(testIntent, /* flags= */ 0, /* startId= */ 0)
- captureCreateCarLifecycleListener()
- carServiceLifecycleListener?.value?.onLifecycleChanged(car, /* ready= */ true)
- captureUxRestrictionsListener()
-
- uxRestrictionsChangedListener?.value?.onUxRestrictionsChanged(noRestrictions)
-
- verify(reminderService).showRecentGrantDecisionsPostDriveNotification()
- }
-
- @Test
- fun onCarReady_registersUxRestrictionListener_restrictionChangeToRestricted_doesNothing() {
- reminderService.onStartCommand(testIntent, /* flags= */ 0, /* startId= */ 0)
- captureCreateCarLifecycleListener()
- carServiceLifecycleListener?.value?.onLifecycleChanged(car, /* ready= */ true)
- captureUxRestrictionsListener()
-
- uxRestrictionsChangedListener?.value?.onUxRestrictionsChanged(fullRestrictions)
-
- verify(reminderService, never()).showRecentGrantDecisionsPostDriveNotification()
- }
-
- @Test
- fun createNotificationContent_1_app_1_permission() {
- reminderService.onStartCommand(testIntent, /* flags= */ 0, /* startId= */ 0)
-
- assertThat(reminderService.createNotificationContent())
- .isEqualTo("While driving, you gave App1 access to Location")
- }
-
- @Test
- fun createNotificationContent_1_app_2_permissions() {
- reminderService.onStartCommand(testIntent, /* flags= */ 0, /* startId= */ 0)
- reminderService.onStartCommand(createIntent(TEST_PACKAGE_1, MICROPHONE_PERMISSION_GROUP),
- /* flags= */ 0, /* startId= */ 0)
-
- assertThat(reminderService.createNotificationContent())
- .isEqualTo("While driving, you gave App1 access to Location & Microphone")
- }
-
- @Test
- fun createNotificationContent_1_app_3_permissions() {
- reminderService.onStartCommand(testIntent, /* flags= */ 0, /* startId= */ 0)
- reminderService.onStartCommand(createIntent(TEST_PACKAGE_1, MICROPHONE_PERMISSION_GROUP),
- /* flags= */ 0, /* startId= */ 0)
- reminderService.onStartCommand(createIntent(TEST_PACKAGE_1, CALENDAR_PERMISSION_GROUP),
- /* flags= */ 0, /* startId= */ 0)
-
- assertThat(reminderService.createNotificationContent())
- .isEqualTo("While driving, you granted 3 permissions to App1")
- }
-
- @Test
- fun createNotificationContent_2_apps() {
- reminderService.onStartCommand(testIntent, /* flags= */ 0, /* startId= */ 0)
- reminderService.onStartCommand(createIntent(TEST_PACKAGE_2, MICROPHONE_PERMISSION_GROUP),
- /* flags= */ 0, /* startId= */ 0)
-
- assertThat(reminderService.createNotificationContent())
- .isEqualTo("While driving, you gave App1 & 1 other app access")
- }
-
- @Test
- fun createNotificationContent_3_apps() {
- reminderService.onStartCommand(testIntent, /* flags= */ 0, /* startId= */ 0)
- reminderService.onStartCommand(createIntent(TEST_PACKAGE_2, MICROPHONE_PERMISSION_GROUP),
- /* flags= */ 0, /* startId= */ 0)
- reminderService.onStartCommand(createIntent(TEST_PACKAGE_3, MICROPHONE_PERMISSION_GROUP),
- /* flags= */ 0, /* startId= */ 0)
-
- assertThat(reminderService.createNotificationContent())
- .isEqualTo("While driving, you gave App1 & 2 other apps access")
- }
-
- private fun captureCreateCarLifecycleListener() {
- ExtendedMockito.verify {
- Car.createCar(any(Context::class.java), any(),
- anyLong(), carServiceLifecycleListener?.capture())
- }
- }
-
- private fun captureUxRestrictionsListener() {
- verify(carUxRestrictionsManager).registerListener(uxRestrictionsChangedListener?.capture())
- }
-} \ No newline at end of file
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/permission/service/NotificationListenerCheckTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/permission/service/v33/NotificationListenerCheckInternalTest.kt
index 4a6573c3e..7da149e31 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/permission/service/NotificationListenerCheckTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/permission/service/v33/NotificationListenerCheckInternalTest.kt
@@ -14,29 +14,28 @@
* limitations under the License.
*/
-package com.android.permissioncontroller.permission.service
+package com.android.permissioncontroller.permission.service.v33
import android.app.job.JobParameters
import android.content.ComponentName
import android.content.Context
+import android.os.Build
import android.provider.DeviceConfig
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
import com.android.dx.mockito.inline.extended.ExtendedMockito
import com.android.permissioncontroller.Constants
-import com.android.permissioncontroller.permission.service.NotificationListenerCheck.NlsComponent
-import com.android.permissioncontroller.permission.service.NotificationListenerCheck.NotificationListenerCheckJobService
+import com.android.permissioncontroller.permission.service.v33.NotificationListenerCheckInternal.NlsComponent
+import com.android.permissioncontroller.permission.service.v33.NotificationListenerCheck.NotificationListenerCheckJobService
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.runBlocking
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.anyBoolean
-import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
-import org.mockito.Mockito.`when` as whenever
import org.mockito.Mockito.mock
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -44,21 +43,22 @@ import org.mockito.MockitoSession
import org.mockito.quality.Strictness
/**
- * Unit tests for internal [NotificationListenerCheck]
+ * Unit tests for [NotificationListenerCheckInternal]
*
* <p> Does not test notification as there are conflicts with being able to mock NotifiationManager
* and PendintIntent.getBroadcast requiring a valid context. Notifications are tested in the CTS
* integration tests
*/
@RunWith(AndroidJUnit4::class)
-class NotificationListenerCheckTest {
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+class NotificationListenerCheckInternalTest {
@Mock
lateinit var notificationListenerCheckJobService: NotificationListenerCheckJobService
private lateinit var context: Context
private lateinit var mockitoSession: MockitoSession
- private lateinit var notificationListenerCheck: NotificationListenerCheck
+ private lateinit var notificationListenerCheck: NotificationListenerCheckInternal
private var shouldCancel = false
@@ -72,10 +72,8 @@ class NotificationListenerCheckTest {
.strictness(Strictness.LENIENT).startMocking()
notificationListenerCheck = runWithShellPermissionIdentity {
- NotificationListenerCheck(context) { shouldCancel }
+ NotificationListenerCheckInternal(context) { shouldCancel }
}
-
- enableNotificationListenerChecker(true)
}
@After
@@ -88,23 +86,6 @@ class NotificationListenerCheckTest {
}
@Test
- fun getEnabledNotificationListenersAndNotifyIfNeeded_featureDisabled_finishJob() {
- enableNotificationListenerChecker(false)
-
- val jobParameters = mock(JobParameters::class.java)
- runWithShellPermissionIdentity {
- runBlocking {
- notificationListenerCheck.getEnabledNotificationListenersAndNotifyIfNeeded(
- jobParameters,
- notificationListenerCheckJobService
- )
- }
- }
-
- verify(notificationListenerCheckJobService).jobFinished(jobParameters, false)
- }
-
- @Test
fun getEnabledNotificationListenersAndNotifyIfNeeded_shouldCancel_finishJob_reschedule() {
shouldCancel = true
val jobParameters = mock(JobParameters::class.java)
@@ -368,16 +349,6 @@ class NotificationListenerCheckTest {
assertThat(updatedNlsComponents).isEmpty()
}
- private fun enableNotificationListenerChecker(enabled: Boolean) {
- whenever(
- DeviceConfig.getBoolean(
- eq(DeviceConfig.NAMESPACE_PRIVACY),
- eq(PROPERTY_NOTIFICATION_LISTENER_CHECK_ENABLED),
- anyBoolean()
- )
- ).thenReturn(enabled)
- }
-
private fun getNotifiedComponents(): Set<NlsComponent> = runBlocking {
notificationListenerCheck.loadNotifiedComponentsLocked()
}
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/permission/ui/model/ReviewPermissionsViewModelTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/permission/ui/model/ReviewPermissionsViewModelTest.kt
new file mode 100644
index 000000000..fd8952dfe
--- /dev/null
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/permission/ui/model/ReviewPermissionsViewModelTest.kt
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.permissioncontroller.permission.ui.model
+
+import android.content.Context
+import android.content.pm.PackageInfo
+import android.content.pm.PackageManager
+import android.os.UserHandle
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.dx.mockito.inline.extended.ExtendedMockito
+import com.android.permissioncontroller.PermissionControllerApplication
+import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup
+import com.android.permissioncontroller.permission.model.livedatatypes.LightPermission
+import com.android.permissioncontroller.permission.ui.model.ReviewPermissionsViewModel.PermissionTarget.PERMISSION_BACKGROUND
+import com.android.permissioncontroller.permission.ui.model.ReviewPermissionsViewModel.PermissionTarget.PERMISSION_BOTH
+import com.android.permissioncontroller.permission.ui.model.ReviewPermissionsViewModel.PermissionTarget.PERMISSION_FOREGROUND
+import com.android.permissioncontroller.permission.ui.model.ReviewPermissionsViewModel.SummaryMessage
+import com.android.permissioncontroller.permission.utils.Utils
+import com.android.settingslib.RestrictedLockUtils
+import org.junit.After
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.spy
+import org.mockito.MockitoAnnotations
+import org.mockito.MockitoSession
+import org.mockito.quality.Strictness
+import org.mockito.Mockito.`when` as whenever
+
+/**
+ * Unit tests for [ReviewPermissionsViewModel]
+ */
+@RunWith(AndroidJUnit4::class)
+class ReviewPermissionsViewModelTest {
+
+ private val testPackageName = "test.package"
+
+ @Mock
+ private lateinit var application: PermissionControllerApplication
+ @Mock
+ private lateinit var permGroup: LightAppPermGroup
+ @Mock
+ private lateinit var foregroundSubGroup: LightAppPermGroup.AppPermSubGroup
+ @Mock
+ private lateinit var backgroundSubGroup: LightAppPermGroup.AppPermSubGroup
+ @Mock
+ private lateinit var admin: RestrictedLockUtils.EnforcedAdmin
+ @Mock
+ private lateinit var packageManager: PackageManager
+
+ private lateinit var mockitoSession: MockitoSession
+ private lateinit var context: Context
+ private lateinit var packageInfo: PackageInfo
+ private lateinit var model: ReviewPermissionsViewModel
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ mockitoSession = ExtendedMockito.mockitoSession()
+ .mockStatic(PermissionControllerApplication::class.java)
+ .mockStatic(Utils::class.java)
+ .strictness(Strictness.LENIENT).startMocking()
+
+ context = ApplicationProvider.getApplicationContext()
+ val userHandle: UserHandle = android.os.Process.myUserHandle()
+ packageInfo = getPackageInfo()
+
+ whenever(packageManager.getPackageInfo(testPackageName, 0)).thenReturn(packageInfo)
+ whenever(PermissionControllerApplication.get()).thenReturn(application)
+ whenever(Utils.getUserContext(application, userHandle)).thenReturn(context)
+ whenever(application.applicationContext).thenReturn(context)
+ whenever(application.packageName).thenReturn(testPackageName)
+ whenever(permGroup.foreground).thenReturn(foregroundSubGroup)
+ whenever(permGroup.background).thenReturn(backgroundSubGroup)
+
+ model = ReviewPermissionsViewModel(application, packageInfo)
+ }
+
+ @After
+ fun finish() {
+ mockitoSession.finishMocking()
+ }
+
+ @Test
+ fun getSummary_individuallyControllerGroup() {
+ val permissionsMap = mutableMapOf<String, LightPermission>()
+ val permission1: LightPermission = mock(LightPermission::class.java)
+ val permission2: LightPermission = mock(LightPermission::class.java)
+ permissionsMap["mockedPermission0"] = permission1
+ permissionsMap["mockedPermission1"] = permission2
+
+ whenever(permGroup.allPermissions).thenReturn(permissionsMap)
+ whenever(permission1.isGrantedIncludingAppOp).thenReturn(true)
+
+ val summary = model.getSummaryForIndividuallyControlledPermGroup(permGroup)
+ assertEquals(
+ ReviewPermissionsViewModel.PermissionSummary(
+ SummaryMessage.REVOKED_COUNT, false, 1
+ ), summary)
+ }
+
+ @Test
+ fun getSummary_foregroundFixedPolicy() {
+ whenever(permGroup.isGranted).thenReturn(true)
+ whenever(foregroundSubGroup.isPolicyFixed).thenReturn(true)
+
+ val summary = model.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_FOREGROUND,
+ permGroup, context)
+ assertEquals(SummaryMessage.ENABLED_BY_POLICY_FOREGROUND_ONLY.toPermSummary(), summary)
+
+ val spyViewModel = spy(model)
+ doReturn(admin).`when`(spyViewModel).getAdmin(context, permGroup)
+ val summaryAdmin = spyViewModel.getSummaryForFixedByPolicyPermissionGroup(
+ PERMISSION_FOREGROUND, permGroup, context)
+ assertEquals(SummaryMessage.ENABLED_BY_ADMIN_FOREGROUND_ONLY.toPermSummary(true),
+ summaryAdmin)
+ }
+
+ @Test
+ fun getSummary_backgroundFixedPolicy_foregroundRequested() {
+ whenever(backgroundSubGroup.isPolicyFixed).thenReturn(true)
+
+ val summary = model.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_FOREGROUND,
+ permGroup, context)
+ assertEquals(SummaryMessage.DISABLED_BY_POLICY_BACKGROUND_ONLY.toPermSummary(), summary)
+
+ val spyViewModel = spy(model)
+ doReturn(admin).`when`(spyViewModel).getAdmin(context, permGroup)
+ val summaryAdmin = spyViewModel.getSummaryForFixedByPolicyPermissionGroup(
+ PERMISSION_FOREGROUND, permGroup, context)
+ assertEquals(SummaryMessage.DISABLED_BY_ADMIN_BACKGROUND_ONLY.toPermSummary(true),
+ summaryAdmin)
+ }
+
+ @Test
+ fun getSummary_backgroundFixedPolicy() {
+ whenever(backgroundSubGroup.isPolicyFixed).thenReturn(true)
+
+ val summary = model.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_BACKGROUND,
+ permGroup, context)
+ assertEquals(SummaryMessage.ENABLED_BY_POLICY_BACKGROUND_ONLY.toPermSummary(), summary)
+
+ val spyViewModel = spy(model)
+ doReturn(admin).`when`(spyViewModel).getAdmin(context, permGroup)
+ val summaryAdmin = spyViewModel.getSummaryForFixedByPolicyPermissionGroup(
+ PERMISSION_BACKGROUND, permGroup, context)
+ assertEquals(SummaryMessage.ENABLED_BY_ADMIN_BACKGROUND_ONLY.toPermSummary(true),
+ summaryAdmin)
+ }
+
+ @Test
+ fun getSummary_fullyFixedPolicy_hasForegroundGroup() {
+ whenever(permGroup.isPolicyFullyFixed).thenReturn(true)
+ whenever(permGroup.hasBackgroundGroup).thenReturn(true)
+
+ val summary = model.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_FOREGROUND,
+ permGroup, context)
+ assertEquals(SummaryMessage.ENABLED_BY_POLICY_BACKGROUND_ONLY.toPermSummary(), summary)
+
+ val spyViewModel = spy(model)
+ doReturn(admin).`when`(spyViewModel).getAdmin(context, permGroup)
+ val summaryAdmin = spyViewModel.getSummaryForFixedByPolicyPermissionGroup(
+ PERMISSION_FOREGROUND, permGroup, context)
+ assertEquals(SummaryMessage.ENABLED_BY_ADMIN_FOREGROUND_ONLY.toPermSummary(), summaryAdmin)
+ }
+
+ @Test
+ fun getSummary_fullyFixedPolicy_hasBackgroundGroup() {
+ whenever(permGroup.isPolicyFullyFixed).thenReturn(true)
+ whenever(permGroup.hasBackgroundGroup).thenReturn(true)
+
+ val summary = model.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_BACKGROUND,
+ permGroup, context)
+ assertEquals(SummaryMessage.ENFORCED_BY_POLICY.toPermSummary(), summary)
+
+ val spyViewModel = spy(model)
+ doReturn(admin).`when`(spyViewModel).getAdmin(context, permGroup)
+ val summaryAdmin = spyViewModel.getSummaryForFixedByPolicyPermissionGroup(
+ PERMISSION_BACKGROUND, permGroup, context)
+ assertEquals(SummaryMessage.ENABLED_BY_ADMIN.toPermSummary(), summaryAdmin)
+ }
+
+ @Test
+ fun getSummary_fullyFixedPolicy_hasNoBackgroundGroup() {
+ whenever(permGroup.isPolicyFullyFixed).thenReturn(true)
+
+ val summary = model.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_BOTH,
+ permGroup, context)
+ assertEquals(SummaryMessage.ENFORCED_BY_POLICY.toPermSummary(), summary)
+
+ val spyViewModel = spy(model)
+ doReturn(admin).`when`(spyViewModel).getAdmin(context, permGroup)
+ val summaryAdmin = spyViewModel.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_BOTH,
+ permGroup, context)
+ assertEquals(SummaryMessage.ENABLED_BY_ADMIN.toPermSummary(), summaryAdmin)
+ }
+
+ @Test
+ fun getSummary_ForegroundDisabledByPolicy() {
+ whenever(foregroundSubGroup.isPolicyFixed).thenReturn(true)
+ whenever(permGroup.isGranted).thenReturn(false)
+
+ val summary = model.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_BOTH,
+ permGroup, context)
+ assertEquals(SummaryMessage.ENFORCED_BY_POLICY.toPermSummary(), summary)
+
+ val spyViewModel = spy(model)
+ doReturn(admin).`when`(spyViewModel).getAdmin(context, permGroup)
+ val adminSummary = spyViewModel.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_BOTH,
+ permGroup, context)
+ assertEquals(SummaryMessage.DISABLED_BY_ADMIN.toPermSummary(), adminSummary)
+ }
+
+ @Test
+ fun getSummary_systemFixedPolicy() {
+ whenever(permGroup.isSystemFixed).thenReturn(true)
+
+ val summary = model.getSummaryForFixedByPolicyPermissionGroup(PERMISSION_BOTH,
+ permGroup, context)
+ assertEquals(SummaryMessage.ENABLED_SYSTEM_FIXED.toPermSummary(), summary)
+ }
+
+ private fun getPackageInfo(): PackageInfo {
+ return PackageInfo().apply {
+ packageName = testPackageName
+ requestedPermissions = listOf<String>().toTypedArray()
+ requestedPermissionsFlags = listOf<Int>().toIntArray()
+ }
+ }
+} \ No newline at end of file
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/privacysources/SafetyCenterReceiverTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/privacysources/SafetyCenterReceiverTest.kt
new file mode 100644
index 000000000..bdcdca618
--- /dev/null
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/privacysources/SafetyCenterReceiverTest.kt
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.permissioncontroller.privacysources
+
+import android.content.Intent
+import android.content.Intent.ACTION_BOOT_COMPLETED
+import android.os.Build
+import android.safetycenter.SafetyCenterManager
+import android.safetycenter.SafetyCenterManager.ACTION_REFRESH_SAFETY_SOURCES
+import android.safetycenter.SafetyCenterManager.ACTION_SAFETY_CENTER_ENABLED_CHANGED
+import android.safetycenter.SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCE_IDS
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
+import com.android.dx.mockito.inline.extended.ExtendedMockito
+import com.android.permissioncontroller.PermissionControllerApplication
+import com.android.permissioncontroller.privacysources.SafetyCenterReceiver.RefreshEvent.EVENT_DEVICE_REBOOTED
+import com.android.permissioncontroller.privacysources.SafetyCenterReceiver.RefreshEvent.EVENT_REFRESH_REQUESTED
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestCoroutineDispatcher
+import kotlinx.coroutines.test.resetMain
+import kotlinx.coroutines.test.runBlockingTest
+import kotlinx.coroutines.test.setMain
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyZeroInteractions
+import org.mockito.MockitoAnnotations
+import org.mockito.MockitoSession
+import org.mockito.quality.Strictness
+
+/**
+ * Unit tests for [SafetyCenterReceiver]
+ */
+@ExperimentalCoroutinesApi
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+class SafetyCenterReceiverTest {
+
+ companion object {
+ private const val TEST_PRIVACY_SOURCE_ID = "test_privacy_source_id"
+ private const val TEST_PRIVACY_SOURCE_ID_2 = "test_privacy_source_id_2"
+
+ val application = Mockito.mock(PermissionControllerApplication::class.java)
+ }
+
+ private val testCoroutineDispatcher: TestCoroutineDispatcher = TestCoroutineDispatcher()
+
+ @Mock
+ lateinit var mockSafetyCenterManager: SafetyCenterManager
+ @Mock
+ lateinit var mockPrivacySource: PrivacySource
+ @Mock
+ lateinit var mockPrivacySource2: PrivacySource
+
+ private lateinit var mockitoSession: MockitoSession
+ private lateinit var safetyCenterReceiver: SafetyCenterReceiver
+
+ private fun privacySourceMap() = mapOf(
+ TEST_PRIVACY_SOURCE_ID to mockPrivacySource,
+ TEST_PRIVACY_SOURCE_ID_2 to mockPrivacySource2
+ )
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+
+ mockitoSession = ExtendedMockito.mockitoSession()
+ .mockStatic(PermissionControllerApplication::class.java)
+ .strictness(Strictness.LENIENT).startMocking()
+
+ whenever(PermissionControllerApplication.get()).thenReturn(application)
+ whenever(application.applicationContext).thenReturn(application)
+ whenever(application.getSystemService(SafetyCenterManager::class.java))
+ .thenReturn(mockSafetyCenterManager)
+ whenever(mockSafetyCenterManager.isSafetyCenterEnabled).thenReturn(true)
+
+ safetyCenterReceiver = SafetyCenterReceiver(::privacySourceMap, testCoroutineDispatcher)
+
+ Dispatchers.setMain(testCoroutineDispatcher)
+ }
+
+ @After
+ fun cleanup() {
+ Dispatchers.resetMain()
+ testCoroutineDispatcher.cleanupTestCoroutines()
+
+ mockitoSession.finishMocking()
+ }
+
+ @Test
+ fun onReceive_actionSafetyCenterEnabledChanged() = runBlockingTest {
+ safetyCenterReceiver.onReceive(application, Intent(ACTION_SAFETY_CENTER_ENABLED_CHANGED))
+
+ verify(mockPrivacySource).safetyCenterEnabledChanged(true)
+ verify(mockPrivacySource2).safetyCenterEnabledChanged(true)
+ }
+
+ @Test
+ fun onReceive_actionSafetyCenterEnabledChanged_safetyCenterDisabled() = runBlockingTest {
+ whenever(mockSafetyCenterManager.isSafetyCenterEnabled).thenReturn(false)
+
+ safetyCenterReceiver.onReceive(application, Intent(ACTION_SAFETY_CENTER_ENABLED_CHANGED))
+ advanceUntilIdle()
+
+ verify(mockPrivacySource).safetyCenterEnabledChanged(false)
+ verify(mockPrivacySource2).safetyCenterEnabledChanged(false)
+ }
+
+ @Test
+ fun onReceive_actionBootCompleted() = runBlockingTest {
+ val intent = Intent(ACTION_BOOT_COMPLETED)
+
+ safetyCenterReceiver.onReceive(application, intent)
+ advanceUntilIdle()
+
+ verify(mockPrivacySource)
+ .rescanAndPushSafetyCenterData(application, intent, EVENT_DEVICE_REBOOTED)
+ verify(mockPrivacySource2)
+ .rescanAndPushSafetyCenterData(application, intent, EVENT_DEVICE_REBOOTED)
+ }
+
+ @Test
+ fun onReceive_actionBootCompleted_safetyCenterDisabled() = runBlockingTest {
+ whenever(mockSafetyCenterManager.isSafetyCenterEnabled).thenReturn(false)
+ val intent = Intent(ACTION_BOOT_COMPLETED)
+
+ safetyCenterReceiver.onReceive(application, intent)
+ advanceUntilIdle()
+
+ verifyZeroInteractions(mockPrivacySource)
+ verifyZeroInteractions(mockPrivacySource2)
+ }
+
+ @Test
+ fun onReceive_actionRefreshSafetySources() = runBlockingTest {
+ val intent = Intent(ACTION_REFRESH_SAFETY_SOURCES)
+ intent.putExtra(EXTRA_REFRESH_SAFETY_SOURCE_IDS, arrayOf(TEST_PRIVACY_SOURCE_ID))
+
+ safetyCenterReceiver.onReceive(application, intent)
+ advanceUntilIdle()
+
+ verify(mockPrivacySource)
+ .rescanAndPushSafetyCenterData(application, intent, EVENT_REFRESH_REQUESTED)
+ verifyZeroInteractions(mockPrivacySource2)
+ }
+
+ @Test
+ fun onReceive_actionRefreshSafetySources_noSourcesSpecified() = runBlockingTest {
+ val intent = Intent(ACTION_REFRESH_SAFETY_SOURCES)
+
+ safetyCenterReceiver.onReceive(application, intent)
+ advanceUntilIdle()
+
+ verifyZeroInteractions(mockPrivacySource)
+ verifyZeroInteractions(mockPrivacySource2)
+ }
+
+ @Test
+ fun onReceive_actionRefreshSafetySources_safetyCenterDisabled() = runBlockingTest {
+ whenever(mockSafetyCenterManager.isSafetyCenterEnabled).thenReturn(false)
+ val intent = Intent(ACTION_REFRESH_SAFETY_SOURCES)
+
+ safetyCenterReceiver.onReceive(application, intent)
+ advanceUntilIdle()
+
+ verifyZeroInteractions(mockPrivacySource)
+ verifyZeroInteractions(mockPrivacySource2)
+ }
+} \ No newline at end of file
diff --git a/SafetyCenter/Config/safety_center_config.xsd b/SafetyCenter/Config/safety_center_config.xsd
index f4adc4721..400380d24 100644
--- a/SafetyCenter/Config/safety_center_config.xsd
+++ b/SafetyCenter/Config/safety_center_config.xsd
@@ -69,10 +69,8 @@
<xsd:attribute name="initialDisplayState" type="initialDisplayState" default="enabled"/>
<xsd:attribute name="maxSeverityLevel" type="xsd:int" default="2147483647"/>
<xsd:attribute name="searchTerms" type="xsd:string"/>
- <xsd:attribute name="broadcastReceiverClassName" type="xsd:string"/>
<xsd:attribute name="loggingAllowed" type="xsd:boolean" default="true"/>
<xsd:attribute name="refreshOnPageOpenAllowed" type="xsd:boolean" default="false"/>
- <xsd:attribute name="automaticNotificationFromIssueAllowed" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:complexType name="issue-only-safety-source">
@@ -81,10 +79,8 @@
<xsd:attribute name="packageName" type="xsd:string" use="required"/>
<xsd:attribute name="profile" type="profile" use="required"/>
<xsd:attribute name="maxSeverityLevel" type="xsd:int" default="2147483647"/>
- <xsd:attribute name="broadcastReceiverClassName" type="xsd:string"/>
<xsd:attribute name="loggingAllowed" type="xsd:boolean" default="true"/>
<xsd:attribute name="refreshOnPageOpenAllowed" type="xsd:boolean" default="false"/>
- <xsd:attribute name="automaticNotificationFromIssueAllowed" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:complexType name="static-safety-source">
diff --git a/SafetyCenter/OWNERS b/SafetyCenter/OWNERS
new file mode 100644
index 000000000..eb1be6327
--- /dev/null
+++ b/SafetyCenter/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 1026964
+
+davidcoffin@google.com
+elliotsisteron@google.com
+kvakil@google.com
diff --git a/SafetyCenter/Resources/AndroidManifest.xml b/SafetyCenter/Resources/AndroidManifest.xml
index a35d54dd3..8129ddb01 100644
--- a/SafetyCenter/Resources/AndroidManifest.xml
+++ b/SafetyCenter/Resources/AndroidManifest.xml
@@ -18,7 +18,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.safetycenter.resources"
coreApp="true"
- android:versionCode="339999900"
+ android:versionCode="330000000"
android:versionName="33 system image">
<application
android:label="@string/safetyCenterResourcesAppLabel"
@@ -34,4 +34,4 @@
</intent-filter>
</activity>
</application>
-</manifest> \ No newline at end of file
+</manifest>
diff --git a/SafetyCenter/Resources/res/values-af/strings.xml b/SafetyCenter/Resources/res/values-af/strings.xml
new file mode 100644
index 000000000..7f688bfb7
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-af/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Veiligheidsentrum-hulpbronne"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Skermslot"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Skermslot"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Bsonderhede sal binnekort beskikbaar wees"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-am/strings.xml b/SafetyCenter/Resources/res/values-am/strings.xml
new file mode 100644
index 000000000..70270bb1e
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-am/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"የደህንነት ማዕከል መርጃዎች"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"የማያ ገጽ ቁልፍ"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"የማያ ገጽ ቁልፍ"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"ዝርዝሩ በቅርቡ ይገኛል"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-as/strings.xml b/SafetyCenter/Resources/res/values-as/strings.xml
new file mode 100644
index 000000000..e511a7a51
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-as/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"সুৰক্ষা কেন্দ্ৰৰ সম্পদ"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"স্ক্ৰীন লক"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"স্ক্ৰীন লক"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"সবিশেষ সোনকালে উপলব্ধ হ’ব"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-az/strings.xml b/SafetyCenter/Resources/res/values-az/strings.xml
new file mode 100644
index 000000000..2ba953d61
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-az/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Təhlükəsizlik Mərkəzi Resursları"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Ekran kilidi"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Ekran kilidi"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Detallar tezliklə əlçatan olacaq"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-b+sr+Latn/strings.xml b/SafetyCenter/Resources/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 000000000..e8a4179b1
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Resursi Centra za bezbednost"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Zaključavanje ekrana"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Zaključavanje ekrana"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Detalji će uskoro biti dostupni"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-be/strings.xml b/SafetyCenter/Resources/res/values-be/strings.xml
new file mode 100644
index 000000000..780fa1295
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-be/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Рэсурсы Цэнтра бяспекі"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Блакіроўка экрана"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Блакіроўка экрана"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Хутка з\'явяцца падрабязныя звесткі"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-bg/strings.xml b/SafetyCenter/Resources/res/values-bg/strings.xml
new file mode 100644
index 000000000..3333f4eee
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-bg/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Ресурси на Центъра за безопасност"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Заключване на екрана"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Заключване на екрана"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Подробностите ще са налице скоро"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-bn/strings.xml b/SafetyCenter/Resources/res/values-bn/strings.xml
new file mode 100644
index 000000000..58a1cb1d4
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-bn/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"সুরক্ষা কেন্দ্র রিসোর্স"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"স্ক্রিন লক"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"স্ক্রিন লক"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"শীঘ্রই এই বিষয়ে তথ্য উপলভ্য হবে"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-bs/strings.xml b/SafetyCenter/Resources/res/values-bs/strings.xml
new file mode 100644
index 000000000..0bf020e99
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-bs/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Izvori Centra za sigurnost"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Zaključavanje ekrana"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Zaključavanje ekrana"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Detalji će biti uskoro dostupni"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ca/strings.xml b/SafetyCenter/Resources/res/values-ca/strings.xml
new file mode 100644
index 000000000..8ee3e80c6
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ca/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Recursos del Centre de seguretat"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Bloqueig de pantalla"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Bloqueig de pantalla"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Aviat hi haurà informació disponible"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-cs/strings.xml b/SafetyCenter/Resources/res/values-cs/strings.xml
new file mode 100644
index 000000000..90d38e827
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-cs/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Zdroje Centra bezpečnosti"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Zámek obrazovky"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Zámek obrazovky"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Podrobnosti budou brzy k dispozici"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-da/strings.xml b/SafetyCenter/Resources/res/values-da/strings.xml
new file mode 100644
index 000000000..d435e504c
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-da/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Ressourcer i Sikkerhedscenter"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Skærmlås"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Skærmlås"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Oplysningerne bliver snart tilgængelige"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-de/strings.xml b/SafetyCenter/Resources/res/values-de/strings.xml
new file mode 100644
index 000000000..99c89fc21
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-de/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Ressourcen für Sicherheitscenter"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Displaysperre"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Displaysperre"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Details sind bald verfügbar"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-el/strings.xml b/SafetyCenter/Resources/res/values-el/strings.xml
new file mode 100644
index 000000000..a91d2f54f
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-el/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Πόροι Κέντρου ασφαλείας"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Κλείδωμα οθόνης"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Κλείδωμα οθόνης"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Σύντομα θα υπάρχουν διαθέσιμες λεπτομέρειες"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-en-rAU/strings.xml b/SafetyCenter/Resources/res/values-en-rAU/strings.xml
new file mode 100644
index 000000000..0801e1cc0
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-en-rAU/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Safety Centre resources"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Screen lock"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Screen lock"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Details available soon"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-en-rCA/strings.xml b/SafetyCenter/Resources/res/values-en-rCA/strings.xml
new file mode 100644
index 000000000..0801e1cc0
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-en-rCA/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Safety Centre resources"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Screen lock"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Screen lock"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Details available soon"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-en-rGB/strings.xml b/SafetyCenter/Resources/res/values-en-rGB/strings.xml
new file mode 100644
index 000000000..0801e1cc0
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-en-rGB/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Safety Centre resources"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Screen lock"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Screen lock"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Details available soon"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-en-rIN/strings.xml b/SafetyCenter/Resources/res/values-en-rIN/strings.xml
new file mode 100644
index 000000000..0801e1cc0
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-en-rIN/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Safety Centre resources"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Screen lock"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Screen lock"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Details available soon"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-en-rXC/strings.xml b/SafetyCenter/Resources/res/values-en-rXC/strings.xml
new file mode 100644
index 000000000..bcb8a7678
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-en-rXC/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‏‏‏‎‎‏‏‎‎‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‏‏‎‏‎‎‏‎‏‏‎‎‏‎‎‎‏‏‎‏‎‎‎‏‏‏‎‏‎‎Safety Center Resources‎‏‎‎‏‎"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‏‏‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‏‏‎‏‏‎‎‎‎‎‎‎‏‏‎‎‏‎‎‎‎‎‏‎‏‏‏‎‏‎‎‏‎‎Screen lock‎‏‎‎‏‎"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‏‏‎‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎‎‎‎‏‏‎‎‎‎‏‏‎‎‏‎‏‎‏‎‏‎‏‎‏‎Screen lock‎‏‎‎‏‎"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‎‎‏‎‎‎‎‎‎‏‎‎‎‏‎‏‎‎‎‏‏‎‏‏‎‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‎‎‏‎‎‎‎‏‎‏‏‏‎Details available soon‎‏‎‎‏‎"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-es-rUS/strings.xml b/SafetyCenter/Resources/res/values-es-rUS/strings.xml
new file mode 100644
index 000000000..d7249472a
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-es-rUS/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Recursos del Centro de seguridad"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Bloqueo de pantalla"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Bloqueo de pantalla"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Próximamente detalles"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-es/strings.xml b/SafetyCenter/Resources/res/values-es/strings.xml
new file mode 100644
index 000000000..ebac2c5c3
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-es/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Recursos del Centro de seguridad"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Bloqueo de pantalla"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Bloqueo de pantalla"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Información disponible próximamente"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-et/strings.xml b/SafetyCenter/Resources/res/values-et/strings.xml
new file mode 100644
index 000000000..c572ef2f3
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-et/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Turbekeskuse ressursid"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Ekraanilukk"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Ekraanilukk"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Üksikasjad on varsti saadaval"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-eu/strings.xml b/SafetyCenter/Resources/res/values-eu/strings.xml
new file mode 100644
index 000000000..3747ee3f3
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-eu/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Segurtasun-zentroko baliabideak"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Pantailaren blokeoa"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Pantailaren blokeoa"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Laster egongo dira erabilgarri xehetasunak"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-fa/strings.xml b/SafetyCenter/Resources/res/values-fa/strings.xml
new file mode 100644
index 000000000..f11f3af88
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-fa/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"منابع مرکز ایمنی"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"قفل صفحه"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"قفل صفحه"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"جزئیات به‌زودی ارائه می‌شود"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-fi/strings.xml b/SafetyCenter/Resources/res/values-fi/strings.xml
new file mode 100644
index 000000000..9cb8886d9
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-fi/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Turvallisuuskeskuksen lisätietoja"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Näytön lukitus"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Näytön lukitus"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Lisätietoa saatavilla pian"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-fr-rCA/strings.xml b/SafetyCenter/Resources/res/values-fr-rCA/strings.xml
new file mode 100644
index 000000000..6cece25d4
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-fr-rCA/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Ressources du centre de sécurité"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Verrouillage de l\'écran"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Verrouillage de l\'écran"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Renseignements bientôt disponibles"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-fr/strings.xml b/SafetyCenter/Resources/res/values-fr/strings.xml
new file mode 100644
index 000000000..9010af712
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-fr/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Ressources du Centre de sécurité"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Verrouillage de l\'écran"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Verrouillage de l\'écran"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Détails bientôt disponibles"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-gl/strings.xml b/SafetyCenter/Resources/res/values-gl/strings.xml
new file mode 100644
index 000000000..cecfe5552
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-gl/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Recursos do Centro de seguranza"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Bloqueo de pantalla"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Bloqueo de pantalla"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Pronto haberá máis información dispoñible"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-gu/strings.xml b/SafetyCenter/Resources/res/values-gu/strings.xml
new file mode 100644
index 000000000..815997fa9
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-gu/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"સુરક્ષા કેન્દ્રના સંસાધનો"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"સ્ક્રીન લૉક"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"સ્ક્રીન લૉક"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"વિગતો ટૂંક સમયમાં ઉપલબ્ધ થશે"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-hi/strings.xml b/SafetyCenter/Resources/res/values-hi/strings.xml
new file mode 100644
index 000000000..2d751d13e
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-hi/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"सुरक्षा केंद्र से जुड़े संसाधन"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"स्क्रीन लॉक"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"स्क्रीन लॉक"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"इसके बारे में जानकारी जल्द ही मौजूद होगी"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-hr/strings.xml b/SafetyCenter/Resources/res/values-hr/strings.xml
new file mode 100644
index 000000000..732d0cba0
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-hr/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Resursi centra za sigurnost"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Zaključavanje zaslona"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Zaključavanje zaslona"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Detalji će biti uskoro dostupni"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-hu/strings.xml b/SafetyCenter/Resources/res/values-hu/strings.xml
new file mode 100644
index 000000000..8b1bacc59
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-hu/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Biztonsági központ erőforrásai"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Képernyőzár"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Képernyőzár"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Részletek hamarosan"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-hy/strings.xml b/SafetyCenter/Resources/res/values-hy/strings.xml
new file mode 100644
index 000000000..f3ca3b5fe
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-hy/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Անվտանգության կենտրոնի ռեսուրսներ"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Էկրանի կողպում"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Էկրանի կողպում"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Մանրամասները շուտով հասանելի կլինեն"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-in/strings.xml b/SafetyCenter/Resources/res/values-in/strings.xml
new file mode 100644
index 000000000..879292382
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-in/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Resource Pusat Keamanan"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Kunci layar"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Kunci layar"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Detail akan segera tersedia"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-is/strings.xml b/SafetyCenter/Resources/res/values-is/strings.xml
new file mode 100644
index 000000000..39c3ae0b3
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-is/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Gögn öryggismiðstöðvar"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Skjálás"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Skjálás"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Upplýsingar í boði fljótlega"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-it/strings.xml b/SafetyCenter/Resources/res/values-it/strings.xml
new file mode 100644
index 000000000..b1d8db5bd
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-it/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Risorse Centro per la sicurezza online"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Blocco schermo"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Blocco schermo"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Dettagli disponibili a breve"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-iw/strings.xml b/SafetyCenter/Resources/res/values-iw/strings.xml
new file mode 100644
index 000000000..1b6cc9b4c
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-iw/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"משאבים למרכז הבטיחות"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"נעילת מסך"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"נעילת מסך"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"הפרטים יהיו זמינים בקרוב"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ja/strings.xml b/SafetyCenter/Resources/res/values-ja/strings.xml
new file mode 100644
index 000000000..b0a637a06
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ja/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"セーフティ センターのリソース"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"画面ロック"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"画面ロック"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"しばらくお待ちください"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ka/strings.xml b/SafetyCenter/Resources/res/values-ka/strings.xml
new file mode 100644
index 000000000..0bd89df85
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ka/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"უსაფრთხოების ცენტრის რესურსები"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"ეკრანის დაბლოკვა"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"ეკრანის დაბლოკვა"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"დეტალები მალე იქნება ხელმისაწვდომი"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-kk/strings.xml b/SafetyCenter/Resources/res/values-kk/strings.xml
new file mode 100644
index 000000000..3c6be54de
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-kk/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Қауіпсіздік орталығының ресурстары"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Экранды құлыптау"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Экранды құлыптау"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Мәліметтер жуырда қолжетімді болады."</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-km/strings.xml b/SafetyCenter/Resources/res/values-km/strings.xml
new file mode 100644
index 000000000..d9ed1aab2
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-km/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"ធនធាននៃមជ្ឈមណ្ឌលសុវត្ថិភាព"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"ការចាក់សោ​អេក្រង់"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"ការចាក់សោ​អេក្រង់"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"ព័ត៌មានលម្អិតនឹងមានឆាប់ៗនេះ"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-kn/strings.xml b/SafetyCenter/Resources/res/values-kn/strings.xml
new file mode 100644
index 000000000..ce474d41d
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-kn/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"ಸುರಕ್ಷತಾ ಕೇಂದ್ರದ ಮಾಹಿತಿಯ ಮೂಲಗಳು"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"ಸ್ಕ್ರೀನ್ ಲಾಕ್"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"ಸ್ಕ್ರೀನ್ ಲಾಕ್"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"ವಿವರಗಳು ಶೀಘ್ರದಲ್ಲೇ ಲಭ್ಯವಾಗಲಿವೆ"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ko/strings.xml b/SafetyCenter/Resources/res/values-ko/strings.xml
new file mode 100644
index 000000000..bb3229eb7
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ko/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"안전 센터 리소스"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"화면 잠금"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"화면 잠금"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"세부정보 제공 예정"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ky/strings.xml b/SafetyCenter/Resources/res/values-ky/strings.xml
new file mode 100644
index 000000000..6f0772998
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ky/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Коопсуздук борборунун ресурстары"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Экранды кулпулоо"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Экранды кулпулоо"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Чоо-жайы жакында жеткиликтүү болот"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-lo/strings.xml b/SafetyCenter/Resources/res/values-lo/strings.xml
new file mode 100644
index 000000000..681c04ab1
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-lo/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"ຊັບ​ພະ​ຍາ​ກອນສູນຄວາມປອດໄພ"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"ລັອກໜ້າຈໍ"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"ລັອກໜ້າຈໍ"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"ຈະມີລາຍລະອຽດໃນອີກບໍ່ດົນ"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-lt/strings.xml b/SafetyCenter/Resources/res/values-lt/strings.xml
new file mode 100644
index 000000000..b9934b535
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-lt/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Saugos centro šaltiniai"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Ekrano užraktas"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Ekrano užraktas"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Išsami informacija bus netrukus pasiekiama"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-lv/strings.xml b/SafetyCenter/Resources/res/values-lv/strings.xml
new file mode 100644
index 000000000..5660975f2
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-lv/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Drošības centra resursi"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Ekrāna bloķēšana"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Ekrāna bloķēšana"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Informācija būs pieejama drīzumā"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-mk/strings.xml b/SafetyCenter/Resources/res/values-mk/strings.xml
new file mode 100644
index 000000000..68143d026
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-mk/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Ресурси на центарот за безбедност"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Заклучување екран"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Заклучување екран"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Деталите ќе бидат достапни наскоро"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ml/strings.xml b/SafetyCenter/Resources/res/values-ml/strings.xml
new file mode 100644
index 000000000..67d925c61
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ml/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"സുരക്ഷാകേന്ദ്ര വിഭവങ്ങൾ"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"സ്ക്രീൻ ലോക്ക്"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"സ്ക്രീൻ ലോക്ക്"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"വിശദാംശങ്ങൾ ഉടൻ ലഭ്യമാകും"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-mn/strings.xml b/SafetyCenter/Resources/res/values-mn/strings.xml
new file mode 100644
index 000000000..7723214eb
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-mn/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Аюулгүй байдлыг хамгаалах төвийн нөөц"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Дэлгэцийн түгжээ"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Дэлгэцийн түгжээ"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Дэлгэрэнгүй мэдээллийг удахгүй авах боломжтой"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-mr/strings.xml b/SafetyCenter/Resources/res/values-mr/strings.xml
new file mode 100644
index 000000000..7c4ce7d7f
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-mr/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"सुरक्षितता केंद्र स्रोत"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"स्क्रीन लॉक"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"स्क्रीन लॉक"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"तपशील लवकरच उपलब्ध होईल"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ms/strings.xml b/SafetyCenter/Resources/res/values-ms/strings.xml
new file mode 100644
index 000000000..3c06cef2a
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ms/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Sumber Pusat Keselamatan"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Kunci skrin"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Kunci skrin"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Butiran tersedia tidak lama lagi"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-my/strings.xml b/SafetyCenter/Resources/res/values-my/strings.xml
new file mode 100644
index 000000000..1173ed085
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-my/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"လုံခြုံရေးစင်တာ ရင်းမြစ်များ"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"ဖန်သားပြင်လော့ခ်"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"ဖန်သားပြင်လော့ခ်"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"မကြာမီ အသေးစိတ်ရနိုင်သည်"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-nb/strings.xml b/SafetyCenter/Resources/res/values-nb/strings.xml
new file mode 100644
index 000000000..45a95ec3b
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-nb/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Ressurser for sikkerhetssenteret"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Skjermlås"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Skjermlås"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Detaljer er snart tilgjengelige"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ne/strings.xml b/SafetyCenter/Resources/res/values-ne/strings.xml
new file mode 100644
index 000000000..66572ecdb
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ne/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"सुरक्षा केन्द्रसम्बन्धी स्रोतहरू"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"स्क्रिन लक"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"स्क्रिन लक"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"विवरणहरू चाँडै नै उपलब्ध हुने छन्"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-nl/strings.xml b/SafetyCenter/Resources/res/values-nl/strings.xml
new file mode 100644
index 000000000..5e914c573
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-nl/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Bronnen voor Veiligheidscentrum"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Schermvergrendeling"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Schermvergrendeling"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Details binnenkort beschikbaar"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-or/strings.xml b/SafetyCenter/Resources/res/values-or/strings.xml
new file mode 100644
index 000000000..afc3b0aa6
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-or/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"ସୁରକ୍ଷା କେନ୍ଦ୍ରର ରିସୋର୍ସଗୁଡ଼ିକ"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"ସ୍କ୍ରିନ ଲକ"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"ସ୍କ୍ରିନ ଲକ"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"ବିବରଣୀ ଶୀଘ୍ର ଉପଲବ୍ଧ ହେବ"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-pa/strings.xml b/SafetyCenter/Resources/res/values-pa/strings.xml
new file mode 100644
index 000000000..b87864925
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-pa/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"ਸੁਰੱਖਿਆ ਕੇਂਦਰ ਸੰਬੰਧੀ ਸਰੋਤ"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"ਸਕ੍ਰੀਨ ਲਾਕ"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"ਸਕ੍ਰੀਨ ਲਾਕ"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"ਵੇਰਵੇ ਜਲਦ ਹੀ ਉਪਲਬਧ ਹੋਣਗੇ"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-pl/strings.xml b/SafetyCenter/Resources/res/values-pl/strings.xml
new file mode 100644
index 000000000..4cde2a470
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-pl/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Zasoby Centrum bezpieczeństwa"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Blokada ekranu"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Blokada ekranu"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Szczegóły wkrótce"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-pt-rBR/strings.xml b/SafetyCenter/Resources/res/values-pt-rBR/strings.xml
new file mode 100644
index 000000000..7c97e665b
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-pt-rBR/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Recursos da Central de segurança"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Bloqueio de tela"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Bloqueio de tela"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Detalhes disponíveis em breve"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-pt-rPT/strings.xml b/SafetyCenter/Resources/res/values-pt-rPT/strings.xml
new file mode 100644
index 000000000..663922e33
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-pt-rPT/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Recursos do Centro de segurança"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Bloqueio de ecrã"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Bloqueio de ecrã"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Detalhes disponíveis em breve"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-pt/strings.xml b/SafetyCenter/Resources/res/values-pt/strings.xml
new file mode 100644
index 000000000..7c97e665b
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-pt/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Recursos da Central de segurança"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Bloqueio de tela"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Bloqueio de tela"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Detalhes disponíveis em breve"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ro/strings.xml b/SafetyCenter/Resources/res/values-ro/strings.xml
new file mode 100644
index 000000000..1611b8e69
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ro/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Resurse din Centrul pentru siguranță"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Blocarea ecranului"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Blocarea ecranului"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Detaliile vor fi disponibile în curând"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ru/strings.xml b/SafetyCenter/Resources/res/values-ru/strings.xml
new file mode 100644
index 000000000..21bca946a
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ru/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Ресурсы центра безопасности"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Блокировка экрана"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Блокировка экрана"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Сведения будут доступны в ближайшее время"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-si/strings.xml b/SafetyCenter/Resources/res/values-si/strings.xml
new file mode 100644
index 000000000..d393c6279
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-si/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"ආරක්ෂක මධ්‍යස්ථාන සම්පත්"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"තිර අගුල"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"තිර අගුල"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"විස්තර ඉක්මනින් ලබා ගත හැකිය"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-sk/strings.xml b/SafetyCenter/Resources/res/values-sk/strings.xml
new file mode 100644
index 000000000..fea1948ed
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-sk/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Zdroje Centra bezpečnosti"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Zámka obrazovky"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Zámka obrazovky"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Podrobnosti budú k dispozícii čoskoro"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-sl/strings.xml b/SafetyCenter/Resources/res/values-sl/strings.xml
new file mode 100644
index 000000000..d2afaa3fd
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-sl/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Viri varnostnega središča"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Zaklepanje zaslona"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Zaklepanje zaslona"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Podrobnosti bodo kmalu na voljo"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-sq/strings.xml b/SafetyCenter/Resources/res/values-sq/strings.xml
new file mode 100644
index 000000000..4c52ca064
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-sq/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Burimet e \"Qendrës së sigurisë\""</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Kyçja e ekranit"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Kyçja e ekranit"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Detajet do të ofrohen së shpejti"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-sr/strings.xml b/SafetyCenter/Resources/res/values-sr/strings.xml
new file mode 100644
index 000000000..1fab6e846
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-sr/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Ресурси Центра за безбедност"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Закључавање екрана"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Закључавање екрана"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Детаљи ће ускоро бити доступни"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-sv/strings.xml b/SafetyCenter/Resources/res/values-sv/strings.xml
new file mode 100644
index 000000000..6de58530f
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-sv/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Resurser i Säkerhetscenter"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Skärmlås"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Skärmlås"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Mer information kommer snart"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-sw/strings.xml b/SafetyCenter/Resources/res/values-sw/strings.xml
new file mode 100644
index 000000000..5e29641ce
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-sw/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Nyenzo za Kituo cha Usalama"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Kufunga skrini"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Kufunga skrini"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Maelezo yatapatikana hivi karibuni"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-te/strings.xml b/SafetyCenter/Resources/res/values-te/strings.xml
new file mode 100644
index 000000000..0a448c661
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-te/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"భద్రతా కేంద్ర రిసోర్స్‌లు"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"స్క్రీన్ లాక్"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"స్క్రీన్ లాక్"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"వివరాలు త్వరలో అందుబాటులో ఉంటాయి"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-th/strings.xml b/SafetyCenter/Resources/res/values-th/strings.xml
new file mode 100644
index 000000000..6eb6b9594
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-th/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"แหล่งข้อมูลของศูนย์ความปลอดภัย"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"ล็อกหน้าจอ"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"ล็อกหน้าจอ"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"จะแจ้งรายละเอียดเร็วๆ นี้"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-tl/strings.xml b/SafetyCenter/Resources/res/values-tl/strings.xml
new file mode 100644
index 000000000..b21321cac
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-tl/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Mga Resource ng Safety Center"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Lock ng screen"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Lock ng screen"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Malapit nang maging available ang mga detalye"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-tr/strings.xml b/SafetyCenter/Resources/res/values-tr/strings.xml
new file mode 100644
index 000000000..567e4730b
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-tr/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Güvenlik Merkezi Kaynakları"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Ekran kilidi"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Ekran kilidi"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Ayrıntılar yakında yayınlanacak"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-uk/strings.xml b/SafetyCenter/Resources/res/values-uk/strings.xml
new file mode 100644
index 000000000..f71d756dd
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-uk/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Ресурси Центру безпеки"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Блокування екрана"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Блокування екрана"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Подробиці будуть незабаром"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-uz/strings.xml b/SafetyCenter/Resources/res/values-uz/strings.xml
new file mode 100644
index 000000000..5d153c366
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-uz/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Xavfsizlik markazi manbalari"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Ekran qulfi"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Ekran qulfi"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Tafsilotlar tez orada chiqadi"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-vi/strings.xml b/SafetyCenter/Resources/res/values-vi/strings.xml
new file mode 100644
index 000000000..5229f82cb
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-vi/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Tài nguyên của trung tâm an toàn"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Phương thức khoá màn hình"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Phương thức khoá màn hình"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Sẽ sớm có thông tin chi tiết"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-zh-rCN/strings.xml b/SafetyCenter/Resources/res/values-zh-rCN/strings.xml
new file mode 100644
index 000000000..a333d72bb
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-zh-rCN/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"安全中心资源"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"屏幕锁定"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"屏幕锁定"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"即将提供详情"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-zh-rHK/strings.xml b/SafetyCenter/Resources/res/values-zh-rHK/strings.xml
new file mode 100644
index 000000000..6a4738bf4
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-zh-rHK/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"安全中心資源"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"螢幕鎖定"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"螢幕鎖定"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"即將顯示詳情"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-zh-rTW/strings.xml b/SafetyCenter/Resources/res/values-zh-rTW/strings.xml
new file mode 100644
index 000000000..ab68db0be
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-zh-rTW/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"安全中心資源"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"螢幕鎖定"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"螢幕鎖定"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"即將顯示詳細資料"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-zu/strings.xml b/SafetyCenter/Resources/res/values-zu/strings.xml
new file mode 100644
index 000000000..308fb5bfa
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-zu/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Izinsiza Zesikhungo Sokuphepha"</string>
+ <string name="lock_screen_sources_title" msgid="7706608329251423698">"Ukukhiya isikrini"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Ukukhiya isikrini"</string>
+ <string name="lock_screen_summary_disabled" msgid="6073123093607694871">"Imininingwane iyatholakala maduze"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/xml/safety_center_config.xml b/SafetyCenter/Resources/res/xml/safety_center_config.xml
index 04374b643..ee555ed86 100644
--- a/SafetyCenter/Resources/res/xml/safety_center_config.xml
+++ b/SafetyCenter/Resources/res/xml/safety_center_config.xml
@@ -27,13 +27,11 @@
summary="@string/lock_screen_summary_disabled"
initialDisplayState="disabled"
packageName="com.android.settings"
- broadcastReceiverClassName="com.android.settings.safetycenter.SafetySourceBroadcastReceiver"
id="LockScreen"/>
<dynamic-safety-source
profile="primary_profile_only"
packageName="com.android.settings"
initialDisplayState="hidden"
- broadcastReceiverClassName="com.android.settings.safetycenter.SafetySourceBroadcastReceiver"
id="Biometrics"/>
</safety-sources-group>
</safety-sources-config>
diff --git a/SafetyCenter/TEST_MAPPING b/SafetyCenter/TEST_MAPPING
new file mode 100644
index 000000000..3985e563c
--- /dev/null
+++ b/SafetyCenter/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsSafetyCenterTestCases"
+ }
+ ]
+}
diff --git a/apex_manifest.json b/apex_manifest.json
index 571465d4c..9fd4129f1 100644
--- a/apex_manifest.json
+++ b/apex_manifest.json
@@ -1,4 +1,4 @@
{
"name": "com.android.permission",
- "version": 339999900
+ "version": 330000000
}
diff --git a/framework-s/api/OWNERS b/framework-s/api/OWNERS
new file mode 100644
index 000000000..72fe70201
--- /dev/null
+++ b/framework-s/api/OWNERS
@@ -0,0 +1 @@
+include /SafetyCenter/OWNERS
diff --git a/framework-s/api/system-current.txt b/framework-s/api/system-current.txt
index 2a28a61c8..483e46165 100644
--- a/framework-s/api/system-current.txt
+++ b/framework-s/api/system-current.txt
@@ -60,7 +60,7 @@ package android.safetycenter {
method public int describeContents();
method @Nullable public android.safetycenter.SafetyCenterEntry.IconAction getIconAction();
method @NonNull public String getId();
- method @NonNull public android.app.PendingIntent getPendingIntent();
+ method @Nullable public android.app.PendingIntent getPendingIntent();
method public int getSeverityLevel();
method public int getSeverityUnspecifiedIconType();
method @Nullable public CharSequence getSummary();
@@ -79,14 +79,14 @@ package android.safetycenter {
}
public static final class SafetyCenterEntry.Builder {
- ctor public SafetyCenterEntry.Builder(@NonNull String);
+ ctor public SafetyCenterEntry.Builder(@NonNull String, @NonNull CharSequence);
ctor public SafetyCenterEntry.Builder(@NonNull android.safetycenter.SafetyCenterEntry);
method @NonNull public android.safetycenter.SafetyCenterEntry build();
method @NonNull public android.safetycenter.SafetyCenterEntry.Builder setEnabled(boolean);
method @NonNull public android.safetycenter.SafetyCenterEntry.Builder setIconAction(@Nullable android.safetycenter.SafetyCenterEntry.IconAction);
method @NonNull public android.safetycenter.SafetyCenterEntry.Builder setIconAction(int, @NonNull android.app.PendingIntent);
method @NonNull public android.safetycenter.SafetyCenterEntry.Builder setId(@NonNull String);
- method @NonNull public android.safetycenter.SafetyCenterEntry.Builder setPendingIntent(@NonNull android.app.PendingIntent);
+ method @NonNull public android.safetycenter.SafetyCenterEntry.Builder setPendingIntent(@Nullable android.app.PendingIntent);
method @NonNull public android.safetycenter.SafetyCenterEntry.Builder setSeverityLevel(int);
method @NonNull public android.safetycenter.SafetyCenterEntry.Builder setSeverityUnspecifiedIconType(int);
method @NonNull public android.safetycenter.SafetyCenterEntry.Builder setSummary(@Nullable CharSequence);
@@ -117,7 +117,7 @@ package android.safetycenter {
}
public static final class SafetyCenterEntryGroup.Builder {
- ctor public SafetyCenterEntryGroup.Builder(@NonNull String);
+ ctor public SafetyCenterEntryGroup.Builder(@NonNull String, @NonNull CharSequence);
ctor public SafetyCenterEntryGroup.Builder(@NonNull android.safetycenter.SafetyCenterEntryGroup);
method @NonNull public android.safetycenter.SafetyCenterEntryGroup build();
method @NonNull public android.safetycenter.SafetyCenterEntryGroup.Builder setEntries(@NonNull java.util.List<android.safetycenter.SafetyCenterEntry>);
@@ -176,8 +176,9 @@ package android.safetycenter {
}
public static final class SafetyCenterIssue.Action.Builder {
- ctor public SafetyCenterIssue.Action.Builder(@NonNull String);
+ ctor public SafetyCenterIssue.Action.Builder(@NonNull String, @NonNull CharSequence, @NonNull android.app.PendingIntent);
method @NonNull public android.safetycenter.SafetyCenterIssue.Action build();
+ method @NonNull public android.safetycenter.SafetyCenterIssue.Action.Builder setId(@NonNull String);
method @NonNull public android.safetycenter.SafetyCenterIssue.Action.Builder setIsInFlight(boolean);
method @NonNull public android.safetycenter.SafetyCenterIssue.Action.Builder setLabel(@NonNull CharSequence);
method @NonNull public android.safetycenter.SafetyCenterIssue.Action.Builder setPendingIntent(@NonNull android.app.PendingIntent);
@@ -186,7 +187,7 @@ package android.safetycenter {
}
public static final class SafetyCenterIssue.Builder {
- ctor public SafetyCenterIssue.Builder(@NonNull String);
+ ctor public SafetyCenterIssue.Builder(@NonNull String, @NonNull CharSequence, @NonNull CharSequence);
ctor public SafetyCenterIssue.Builder(@NonNull android.safetycenter.SafetyCenterIssue);
method @NonNull public android.safetycenter.SafetyCenterIssue build();
method @NonNull public android.safetycenter.SafetyCenterIssue.Builder setActions(@NonNull java.util.List<android.safetycenter.SafetyCenterIssue.Action>);
@@ -201,24 +202,29 @@ package android.safetycenter {
public final class SafetyCenterManager {
method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void addOnSafetyCenterDataChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.safetycenter.SafetyCenterManager.OnSafetyCenterDataChangedListener);
- method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void clearAllSafetySourceData();
- method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void clearSafetyCenterConfigOverride();
+ method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void clearAllSafetySourceDataForTests();
+ method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void clearSafetyCenterConfigForTests();
method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void dismissSafetyCenterIssue(@NonNull String);
method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void executeSafetyCenterIssueAction(@NonNull String, @NonNull String);
+ method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public android.safetycenter.config.SafetyCenterConfig getSafetyCenterConfig();
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public android.safetycenter.SafetyCenterData getSafetyCenterData();
method @Nullable @RequiresPermission(android.Manifest.permission.SEND_SAFETY_CENTER_UPDATE) public android.safetycenter.SafetySourceData getSafetySourceData(@NonNull String);
method @RequiresPermission(anyOf={android.Manifest.permission.READ_SAFETY_CENTER_STATUS, android.Manifest.permission.SEND_SAFETY_CENTER_UPDATE}) public boolean isSafetyCenterEnabled();
method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void refreshSafetySources(int);
method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void removeOnSafetyCenterDataChangedListener(@NonNull android.safetycenter.SafetyCenterManager.OnSafetyCenterDataChangedListener);
method @RequiresPermission(android.Manifest.permission.SEND_SAFETY_CENTER_UPDATE) public void reportSafetySourceError(@NonNull String, @NonNull android.safetycenter.SafetySourceErrorDetails);
- method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void setSafetyCenterConfigOverride(@NonNull android.safetycenter.config.SafetyCenterConfig);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void setSafetyCenterConfigForTests(@NonNull android.safetycenter.config.SafetyCenterConfig);
method @RequiresPermission(android.Manifest.permission.SEND_SAFETY_CENTER_UPDATE) public void setSafetySourceData(@NonNull String, @Nullable android.safetycenter.SafetySourceData, @NonNull android.safetycenter.SafetyEvent);
field public static final String ACTION_REFRESH_SAFETY_SOURCES = "android.safetycenter.action.REFRESH_SAFETY_SOURCES";
+ field public static final String ACTION_SAFETY_CENTER_ENABLED_CHANGED = "android.safetycenter.action.SAFETY_CENTER_ENABLED_CHANGED";
field public static final int EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA = 0; // 0x0
field public static final int EXTRA_REFRESH_REQUEST_TYPE_GET_DATA = 1; // 0x1
field public static final String EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID = "android.safetycenter.extra.REFRESH_SAFETY_SOURCES_BROADCAST_ID";
field public static final String EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE = "android.safetycenter.extra.REFRESH_SAFETY_SOURCES_REQUEST_TYPE";
field public static final String EXTRA_REFRESH_SAFETY_SOURCE_IDS = "android.safetycenter.extra.REFRESH_SAFETY_SOURCE_IDS";
+ field public static final String EXTRA_SAFETY_SOURCE_ID = "android.safetycenter.extra.SAFETY_SOURCE_ID";
+ field public static final String EXTRA_SAFETY_SOURCE_ISSUE_ID = "android.safetycenter.extra.SAFETY_SOURCE_ISSUE_ID";
+ field public static final String EXTRA_SAFETY_SOURCE_USER_HANDLE = "android.safetycenter.extra.SAFETY_SOURCE_USER_HANDLE";
field public static final int REFRESH_REASON_DEVICE_LOCALE_CHANGE = 400; // 0x190
field public static final int REFRESH_REASON_DEVICE_REBOOT = 300; // 0x12c
field public static final int REFRESH_REASON_OTHER = 600; // 0x258
@@ -233,15 +239,23 @@ package android.safetycenter {
}
public final class SafetyCenterStaticEntry implements android.os.Parcelable {
- ctor public SafetyCenterStaticEntry(@NonNull CharSequence, @Nullable CharSequence, @NonNull android.app.PendingIntent);
method public int describeContents();
- method @NonNull public android.app.PendingIntent getPendingIntent();
+ method @Nullable public android.app.PendingIntent getPendingIntent();
method @Nullable public CharSequence getSummary();
method @NonNull public CharSequence getTitle();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.safetycenter.SafetyCenterStaticEntry> CREATOR;
}
+ public static final class SafetyCenterStaticEntry.Builder {
+ ctor public SafetyCenterStaticEntry.Builder(@NonNull CharSequence);
+ ctor public SafetyCenterStaticEntry.Builder(@NonNull android.safetycenter.SafetyCenterStaticEntry);
+ method @NonNull public android.safetycenter.SafetyCenterStaticEntry build();
+ method @NonNull public android.safetycenter.SafetyCenterStaticEntry.Builder setPendingIntent(@Nullable android.app.PendingIntent);
+ method @NonNull public android.safetycenter.SafetyCenterStaticEntry.Builder setSummary(@Nullable CharSequence);
+ method @NonNull public android.safetycenter.SafetyCenterStaticEntry.Builder setTitle(@NonNull CharSequence);
+ }
+
public final class SafetyCenterStaticEntryGroup implements android.os.Parcelable {
ctor public SafetyCenterStaticEntryGroup(@NonNull CharSequence, @NonNull java.util.List<android.safetycenter.SafetyCenterStaticEntry>);
method public int describeContents();
@@ -269,7 +283,7 @@ package android.safetycenter {
}
public static final class SafetyCenterStatus.Builder {
- ctor public SafetyCenterStatus.Builder();
+ ctor public SafetyCenterStatus.Builder(@NonNull CharSequence, @NonNull CharSequence);
ctor public SafetyCenterStatus.Builder(@NonNull android.safetycenter.SafetyCenterStatus);
method @NonNull public android.safetycenter.SafetyCenterStatus build();
method @NonNull public android.safetycenter.SafetyCenterStatus.Builder setRefreshStatus(int);
@@ -308,6 +322,10 @@ package android.safetycenter {
method @Nullable public android.safetycenter.SafetySourceStatus getStatus();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.safetycenter.SafetySourceData> CREATOR;
+ field public static final int SEVERITY_LEVEL_CRITICAL_WARNING = 400; // 0x190
+ field public static final int SEVERITY_LEVEL_INFORMATION = 200; // 0xc8
+ field public static final int SEVERITY_LEVEL_RECOMMENDATION = 300; // 0x12c
+ field public static final int SEVERITY_LEVEL_UNSPECIFIED = 100; // 0x64
}
public static final class SafetySourceData.Builder {
@@ -342,9 +360,6 @@ package android.safetycenter {
field public static final int ISSUE_CATEGORY_ACCOUNT = 200; // 0xc8
field public static final int ISSUE_CATEGORY_DEVICE = 100; // 0x64
field public static final int ISSUE_CATEGORY_GENERAL = 300; // 0x12c
- field public static final int SEVERITY_LEVEL_CRITICAL_WARNING = 400; // 0x190
- field public static final int SEVERITY_LEVEL_INFORMATION = 200; // 0xc8
- field public static final int SEVERITY_LEVEL_RECOMMENDATION = 300; // 0x12c
}
public static final class SafetySourceIssue.Action implements android.os.Parcelable {
@@ -378,24 +393,21 @@ package android.safetycenter {
public final class SafetySourceStatus implements android.os.Parcelable {
method public int describeContents();
method @Nullable public android.safetycenter.SafetySourceStatus.IconAction getIconAction();
- method @NonNull public android.app.PendingIntent getPendingIntent();
- method public int getStatusLevel();
+ method @Nullable public android.app.PendingIntent getPendingIntent();
+ method public int getSeverityLevel();
method @NonNull public CharSequence getSummary();
method @NonNull public CharSequence getTitle();
method public boolean isEnabled();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.safetycenter.SafetySourceStatus> CREATOR;
- field public static final int STATUS_LEVEL_CRITICAL_WARNING = 400; // 0x190
- field public static final int STATUS_LEVEL_NONE = 100; // 0x64
- field public static final int STATUS_LEVEL_OK = 200; // 0xc8
- field public static final int STATUS_LEVEL_RECOMMENDATION = 300; // 0x12c
}
public static final class SafetySourceStatus.Builder {
- ctor public SafetySourceStatus.Builder(@NonNull CharSequence, @NonNull CharSequence, int, @NonNull android.app.PendingIntent);
+ ctor public SafetySourceStatus.Builder(@NonNull CharSequence, @NonNull CharSequence, int);
method @NonNull public android.safetycenter.SafetySourceStatus build();
method @NonNull public android.safetycenter.SafetySourceStatus.Builder setEnabled(boolean);
method @NonNull public android.safetycenter.SafetySourceStatus.Builder setIconAction(@Nullable android.safetycenter.SafetySourceStatus.IconAction);
+ method @NonNull public android.safetycenter.SafetySourceStatus.Builder setPendingIntent(@Nullable android.app.PendingIntent);
}
public static final class SafetySourceStatus.IconAction implements android.os.Parcelable {
@@ -434,7 +446,6 @@ package android.safetycenter.config {
public final class SafetySource implements android.os.Parcelable {
method public int describeContents();
- method @Nullable public String getBroadcastReceiverClassName();
method @NonNull public String getId();
method public int getInitialDisplayState();
method @Nullable public String getIntentAction();
@@ -446,7 +457,6 @@ package android.safetycenter.config {
method @StringRes public int getTitleForWorkResId();
method @StringRes public int getTitleResId();
method public int getType();
- method public boolean isAutomaticNotificationFromIssueAllowed();
method public boolean isLoggingAllowed();
method public boolean isRefreshOnPageOpenAllowed();
method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -465,8 +475,6 @@ package android.safetycenter.config {
public static final class SafetySource.Builder {
ctor public SafetySource.Builder(int);
method @NonNull public android.safetycenter.config.SafetySource build();
- method @NonNull public android.safetycenter.config.SafetySource.Builder setAutomaticNotificationFromIssueAllowed(boolean);
- method @NonNull public android.safetycenter.config.SafetySource.Builder setBroadcastReceiverClassName(@Nullable String);
method @NonNull public android.safetycenter.config.SafetySource.Builder setId(@Nullable String);
method @NonNull public android.safetycenter.config.SafetySource.Builder setInitialDisplayState(int);
method @NonNull public android.safetycenter.config.SafetySource.Builder setIntentAction(@Nullable String);
diff --git a/framework-s/java/android/safetycenter/ISafetyCenterManager.aidl b/framework-s/java/android/safetycenter/ISafetyCenterManager.aidl
index 902b9f684..9805090be 100644
--- a/framework-s/java/android/safetycenter/ISafetyCenterManager.aidl
+++ b/framework-s/java/android/safetycenter/ISafetyCenterManager.aidl
@@ -72,6 +72,9 @@ interface ISafetyCenterManager {
/** Requests safety sources to set their latest SafetySourceData for Safety Center. */
void refreshSafetySources(int refreshReason, int userId);
+ /** Returns the current SafetyCenterConfig, if available. */
+ SafetyCenterConfig getSafetyCenterConfig();
+
/**
* Returns the current SafetyCenterData, assembled from the SafetySourceData from all sources.
*/
@@ -98,31 +101,31 @@ interface ISafetyCenterManager {
int userId);
/**
- * Clears all SafetySourceData set by safety sources using setSafetySourceData.
+ * Clears all SafetySourceData (set by safety sources using setSafetySourceData) for testing.
*
* <p>Note: This API serves to facilitate CTS testing and should not be used for other purposes.
*/
- void clearAllSafetySourceData();
+ void clearAllSafetySourceDataForTests();
/**
- * Sets an override of the SafetyCenterConfig set through XML.
+ * Overrides the SafetyCenterConfig for testing.
*
- * When set, the override SafetyCenterConfig will be used instead of the
+ * <p>When set, the overridden SafetyCenterConfig will be used instead of the
* SafetyCenterConfig parsed from the XML file to read configured safety sources.
*
* <p>Note: This API serves to facilitate CTS testing and should not be used to configure safety
* sources dynamically for production. Once used for testing, the override should be cleared.
*
- * See clearSafetyCenterConfigOverride.
+ * See clearSafetyCenterConfigForTests.
*/
- void setSafetyCenterConfigOverride(in SafetyCenterConfig safetyCenterConfig);
+ void setSafetyCenterConfigForTests(in SafetyCenterConfig safetyCenterConfig);
/**
- * Clears the override of the SafetyCenterConfig set through XML.
+ * Clears the override of the SafetyCenterConfig set for testing.
*
* <p>Note: This API serves to facilitate CTS testing and should not be used for other purposes.
*
- * See setSafetyCenterConfigOverride(SafetyCenterConfig).
+ * See setSafetyCenterConfigForTests(SafetyCenterConfig).
*/
- void clearSafetyCenterConfigOverride();
+ void clearSafetyCenterConfigForTests();
} \ No newline at end of file
diff --git a/framework-s/java/android/safetycenter/OWNERS b/framework-s/java/android/safetycenter/OWNERS
new file mode 100644
index 000000000..72fe70201
--- /dev/null
+++ b/framework-s/java/android/safetycenter/OWNERS
@@ -0,0 +1 @@
+include /SafetyCenter/OWNERS
diff --git a/framework-s/java/android/safetycenter/SafetyCenterData.java b/framework-s/java/android/safetycenter/SafetyCenterData.java
index c5beb7b52..b987191ce 100644
--- a/framework-s/java/android/safetycenter/SafetyCenterData.java
+++ b/framework-s/java/android/safetycenter/SafetyCenterData.java
@@ -18,6 +18,7 @@ package android.safetycenter;
import static android.os.Build.VERSION_CODES.TIRAMISU;
+import static java.util.Collections.unmodifiableList;
import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
@@ -41,6 +42,27 @@ import java.util.Objects;
public final class SafetyCenterData implements Parcelable {
@NonNull
+ public static final Creator<SafetyCenterData> CREATOR =
+ new Creator<SafetyCenterData>() {
+ @Override
+ public SafetyCenterData createFromParcel(Parcel in) {
+ SafetyCenterStatus status = in.readTypedObject(SafetyCenterStatus.CREATOR);
+ List<SafetyCenterIssue> issues = in.createTypedArrayList(
+ SafetyCenterIssue.CREATOR);
+ List<SafetyCenterEntryOrGroup> entryOrGroups =
+ in.createTypedArrayList(SafetyCenterEntryOrGroup.CREATOR);
+ List<SafetyCenterStaticEntryGroup> staticEntryGroups =
+ in.createTypedArrayList(SafetyCenterStaticEntryGroup.CREATOR);
+ return new SafetyCenterData(status, issues, entryOrGroups, staticEntryGroups);
+ }
+
+ @Override
+ public SafetyCenterData[] newArray(int size) {
+ return new SafetyCenterData[size];
+ }
+ };
+
+ @NonNull
private final SafetyCenterStatus mStatus;
@NonNull
private final List<SafetyCenterIssue> mIssues;
@@ -49,8 +71,6 @@ public final class SafetyCenterData implements Parcelable {
@NonNull
private final List<SafetyCenterStaticEntryGroup> mStaticEntryGroups;
- //TODO(b/208415162): Add support for static/advanced entries.
-
/** Creates a {@link SafetyCenterData}. */
public SafetyCenterData(
@NonNull SafetyCenterStatus status,
@@ -58,9 +78,9 @@ public final class SafetyCenterData implements Parcelable {
@NonNull List<SafetyCenterEntryOrGroup> entriesOrGroups,
@NonNull List<SafetyCenterStaticEntryGroup> staticEntryGroups) {
mStatus = requireNonNull(status);
- mIssues = new ArrayList<>(issues);
- mEntriesOrGroups = new ArrayList<>(entriesOrGroups);
- mStaticEntryGroups = new ArrayList<>(staticEntryGroups);
+ mIssues = unmodifiableList(new ArrayList<>(requireNonNull(issues)));
+ mEntriesOrGroups = unmodifiableList(new ArrayList<>(requireNonNull(entriesOrGroups)));
+ mStaticEntryGroups = unmodifiableList(new ArrayList<>(requireNonNull(staticEntryGroups)));
}
/** Returns the overall {@link SafetyCenterStatus} of the Safety Center. */
@@ -72,7 +92,7 @@ public final class SafetyCenterData implements Parcelable {
/** Returns the list of active {@link SafetyCenterIssue} objects in the Safety Center. */
@NonNull
public List<SafetyCenterIssue> getIssues() {
- return new ArrayList<>(mIssues);
+ return mIssues;
}
/**
@@ -81,21 +101,19 @@ public final class SafetyCenterData implements Parcelable {
*/
@NonNull
public List<SafetyCenterEntryOrGroup> getEntriesOrGroups() {
- return new ArrayList<>(mEntriesOrGroups);
+ return mEntriesOrGroups;
}
- /**
- * Returns the list of {@link SafetyCenterStaticEntryGroup} objects in the Safety Center.
- */
+ /** Returns the list of {@link SafetyCenterStaticEntryGroup} objects in the Safety Center. */
@NonNull
public List<SafetyCenterStaticEntryGroup> getStaticEntryGroups() {
- return new ArrayList<>(mStaticEntryGroups);
+ return mStaticEntryGroups;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (!(o instanceof SafetyCenterData)) return false;
SafetyCenterData that = (SafetyCenterData) o;
return Objects.equals(mStatus, that.mStatus)
&& Objects.equals(mIssues, that.mIssues)
@@ -111,10 +129,14 @@ public final class SafetyCenterData implements Parcelable {
@Override
public String toString() {
return "SafetyCenterData{"
- + "mStatus=" + mStatus
- + ", mIssues=" + mIssues
- + ", mEntriesOrGroups=" + mEntriesOrGroups
- + ", mStaticEntryGroups=" + mStaticEntryGroups
+ + "mStatus="
+ + mStatus
+ + ", mIssues="
+ + mIssues
+ + ", mEntriesOrGroups="
+ + mEntriesOrGroups
+ + ", mStaticEntryGroups="
+ + mStaticEntryGroups
+ '}';
}
@@ -125,27 +147,9 @@ public final class SafetyCenterData implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeParcelable(mStatus, flags);
+ dest.writeTypedObject(mStatus, flags);
dest.writeTypedList(mIssues);
dest.writeTypedList(mEntriesOrGroups);
dest.writeTypedList(mStaticEntryGroups);
}
-
- @NonNull
- public static final Creator<SafetyCenterData> CREATOR = new Creator<SafetyCenterData>() {
- @Override
- public SafetyCenterData createFromParcel(Parcel in) {
- return new SafetyCenterData(
- in.readParcelable(
- SafetyCenterStatus.class.getClassLoader(), SafetyCenterStatus.class),
- in.createTypedArrayList(SafetyCenterIssue.CREATOR),
- in.createTypedArrayList(SafetyCenterEntryOrGroup.CREATOR),
- in.createTypedArrayList(SafetyCenterStaticEntryGroup.CREATOR));
- }
-
- @Override
- public SafetyCenterData[] newArray(int size) {
- return new SafetyCenterData[size];
- }
- };
}
diff --git a/framework-s/java/android/safetycenter/SafetyCenterEntry.java b/framework-s/java/android/safetycenter/SafetyCenterEntry.java
index 33c790289..374a977c2 100644
--- a/framework-s/java/android/safetycenter/SafetyCenterEntry.java
+++ b/framework-s/java/android/safetycenter/SafetyCenterEntry.java
@@ -39,8 +39,8 @@ import java.util.Objects;
* An individual entry in the Safety Center.
*
* <p>A {@link SafetyCenterEntry} conveys the current status of an individual safety feature on the
- * device. Entries are present even if they have no associated active issues. In contrast, a
- * {@link SafetyCenterIssue} is ephemeral and disappears when the issue is resolved.
+ * device. Entries are present even if they have no associated active issues. In contrast, a {@link
+ * SafetyCenterIssue} is ephemeral and disappears when the issue is resolved.
*
* <p>Entries link to their corresponding component or an action on it via {@link
* #getPendingIntent()}.
@@ -52,25 +52,6 @@ import java.util.Objects;
public final class SafetyCenterEntry implements Parcelable {
/**
- * All possible severity levels for a {@link SafetyCenterEntry}.
- *
- * @see SafetyCenterEntry#getSeverityLevel()
- * @see Builder#setSeverityLevel(int)
- *
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = "ENTRY_SEVERITY_LEVEL_", value = {
- ENTRY_SEVERITY_LEVEL_UNKNOWN,
- ENTRY_SEVERITY_LEVEL_UNSPECIFIED,
- ENTRY_SEVERITY_LEVEL_OK,
- ENTRY_SEVERITY_LEVEL_RECOMMENDATION,
- ENTRY_SEVERITY_LEVEL_CRITICAL_WARNING,
- })
- public @interface EntrySeverityLevel {
- }
-
- /**
* Indicates the severity level of this entry is not currently known. This may be because of an
* error or because some information is missing.
*/
@@ -79,8 +60,8 @@ public final class SafetyCenterEntry implements Parcelable {
/**
* Indicates this entry does not have a severity level.
*
- * <p>This is used when the Safety Center has no opinion on the severity of this entry (e.g.
- * a security setting isn't configured but it's not considered a risk, or for privacy-related
+ * <p>This is used when the Safety Center has no opinion on the severity of this entry (e.g. a
+ * security setting isn't configured, but it's not considered a risk, or for privacy-related
* entries).
*/
public static final int ENTRY_SEVERITY_LEVEL_UNSPECIFIED = 3100;
@@ -95,21 +76,23 @@ public final class SafetyCenterEntry implements Parcelable {
public static final int ENTRY_SEVERITY_LEVEL_CRITICAL_WARNING = 3400;
/**
- * All possible icon types for a {@link SafetyCenterEntry} to use when its severity level is
- * {@link #ENTRY_SEVERITY_LEVEL_UNSPECIFIED}.
- *
- * <p>It is only relevant when the entry's severity level is {@link
- * #ENTRY_SEVERITY_LEVEL_UNSPECIFIED}.
+ * All possible severity levels for a {@link SafetyCenterEntry}.
*
* @hide
+ * @see SafetyCenterEntry#getSeverityLevel()
+ * @see Builder#setSeverityLevel(int)
*/
@Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = "SEVERITY_UNSPECIFIED_ICON_TYPE_", value = {
- SEVERITY_UNSPECIFIED_ICON_TYPE_NO_ICON,
- SEVERITY_UNSPECIFIED_ICON_TYPE_PRIVACY,
- SEVERITY_UNSPECIFIED_ICON_TYPE_NO_RECOMMENDATION,
- })
- public @interface SeverityUnspecifiedIconType {
+ @IntDef(
+ prefix = "ENTRY_SEVERITY_LEVEL_",
+ value = {
+ ENTRY_SEVERITY_LEVEL_UNKNOWN,
+ ENTRY_SEVERITY_LEVEL_UNSPECIFIED,
+ ENTRY_SEVERITY_LEVEL_OK,
+ ENTRY_SEVERITY_LEVEL_RECOMMENDATION,
+ ENTRY_SEVERITY_LEVEL_CRITICAL_WARNING,
+ })
+ public @interface EntrySeverityLevel {
}
/** Indicates an entry with {@link #ENTRY_SEVERITY_LEVEL_UNSPECIFIED} should not use an icon. */
@@ -127,6 +110,48 @@ public final class SafetyCenterEntry implements Parcelable {
*/
public static final int SEVERITY_UNSPECIFIED_ICON_TYPE_NO_RECOMMENDATION = 2;
+ /**
+ * All possible icon types for a {@link SafetyCenterEntry} to use when its severity level is
+ * {@link #ENTRY_SEVERITY_LEVEL_UNSPECIFIED}.
+ *
+ * <p>It is only relevant when the entry's severity level is {@link
+ * #ENTRY_SEVERITY_LEVEL_UNSPECIFIED}.
+ *
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(
+ prefix = "SEVERITY_UNSPECIFIED_ICON_TYPE_",
+ value = {
+ SEVERITY_UNSPECIFIED_ICON_TYPE_NO_ICON,
+ SEVERITY_UNSPECIFIED_ICON_TYPE_PRIVACY,
+ SEVERITY_UNSPECIFIED_ICON_TYPE_NO_RECOMMENDATION,
+ })
+ public @interface SeverityUnspecifiedIconType {
+ }
+
+ @NonNull
+ public static final Creator<SafetyCenterEntry> CREATOR =
+ new Creator<SafetyCenterEntry>() {
+ @Override
+ public SafetyCenterEntry createFromParcel(Parcel in) {
+ String id = in.readString();
+ CharSequence title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ return new Builder(id, title)
+ .setSummary(TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in))
+ .setSeverityLevel(in.readInt())
+ .setSeverityUnspecifiedIconType(in.readInt())
+ .setEnabled(in.readBoolean())
+ .setPendingIntent(in.readTypedObject(PendingIntent.CREATOR))
+ .setIconAction(in.readTypedObject(IconAction.CREATOR))
+ .build();
+ }
+
+ @Override
+ public SafetyCenterEntry[] newArray(int size) {
+ return new SafetyCenterEntry[size];
+ }
+ };
@NonNull
private final String mId;
@@ -139,7 +164,7 @@ public final class SafetyCenterEntry implements Parcelable {
@SeverityUnspecifiedIconType
private final int mSeverityUnspecifiedIconType;
private final boolean mEnabled;
- @NonNull
+ @Nullable
private final PendingIntent mPendingIntent;
@Nullable
private final IconAction mIconAction;
@@ -151,15 +176,15 @@ public final class SafetyCenterEntry implements Parcelable {
@EntrySeverityLevel int severityLevel,
@SeverityUnspecifiedIconType int severityUnspecifiedIconType,
boolean enabled,
- @NonNull PendingIntent pendingIntent,
+ @Nullable PendingIntent pendingIntent,
@Nullable IconAction iconAction) {
- mId = requireNonNull(id);
- mTitle = requireNonNull(title);
+ mId = id;
+ mTitle = title;
mSummary = summary;
mSeverityLevel = severityLevel;
mSeverityUnspecifiedIconType = severityUnspecifiedIconType;
mEnabled = enabled;
- mPendingIntent = requireNonNull(pendingIntent);
+ mPendingIntent = pendingIntent;
mIconAction = iconAction;
}
@@ -196,20 +221,22 @@ public final class SafetyCenterEntry implements Parcelable {
return mSeverityUnspecifiedIconType;
}
- /** Returns whether or not this entry is enabled. */
+ /** Returns whether this entry is enabled. */
public boolean isEnabled() {
return mEnabled;
}
- /** Returns the {@link PendingIntent} to execute when this entry is selected. */
- @NonNull
+ /**
+ * Returns the optional {@link PendingIntent} to execute when this entry is selected if present,
+ * or {@code null} otherwise.
+ */
+ @Nullable
public PendingIntent getPendingIntent() {
return mPendingIntent;
}
/**
- * Returns the optional {@link IconAction} for this entry if present, or {@code null}
- * otherwise.
+ * Returns the optional {@link IconAction} for this entry if present, or {@code null} otherwise.
*/
@Nullable
public IconAction getIconAction() {
@@ -219,7 +246,7 @@ public final class SafetyCenterEntry implements Parcelable {
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (!(o instanceof SafetyCenterEntry)) return false;
SafetyCenterEntry that = (SafetyCenterEntry) o;
return mSeverityLevel == that.mSeverityLevel
&& mSeverityUnspecifiedIconType == that.mSeverityUnspecifiedIconType
@@ -233,21 +260,37 @@ public final class SafetyCenterEntry implements Parcelable {
@Override
public int hashCode() {
- return Objects.hash(mId, mTitle, mSummary, mSeverityLevel, mSeverityUnspecifiedIconType,
- mEnabled, mPendingIntent, mIconAction);
+ return Objects.hash(
+ mId,
+ mTitle,
+ mSummary,
+ mSeverityLevel,
+ mSeverityUnspecifiedIconType,
+ mEnabled,
+ mPendingIntent,
+ mIconAction);
}
@Override
public String toString() {
return "SafetyCenterEntry{"
- + "mId='" + mId + '\''
- + ", mTitle=" + mTitle
- + ", mSummary=" + mSummary
- + ", mSeverityLevel=" + mSeverityLevel
- + ", mSeverityUnspecifiedIconType=" + mSeverityUnspecifiedIconType
- + ", mEnabled=" + mEnabled
- + ", mAction=" + mPendingIntent
- + ", mIconAction=" + mIconAction
+ + "mId='"
+ + mId
+ + '\''
+ + ", mTitle="
+ + mTitle
+ + ", mSummary="
+ + mSummary
+ + ", mSeverityLevel="
+ + mSeverityLevel
+ + ", mSeverityUnspecifiedIconType="
+ + mSeverityUnspecifiedIconType
+ + ", mEnabled="
+ + mEnabled
+ + ", mPendingIntent="
+ + mPendingIntent
+ + ", mIconAction="
+ + mIconAction
+ '}';
}
@@ -264,62 +307,41 @@ public final class SafetyCenterEntry implements Parcelable {
dest.writeInt(mSeverityLevel);
dest.writeInt(mSeverityUnspecifiedIconType);
dest.writeBoolean(mEnabled);
- dest.writeParcelable(mPendingIntent, flags);
- dest.writeParcelable(mIconAction, flags);
+ dest.writeTypedObject(mPendingIntent, flags);
+ dest.writeTypedObject(mIconAction, flags);
}
- @NonNull
- public static final Creator<SafetyCenterEntry> CREATOR = new Creator<SafetyCenterEntry>() {
- @Override
- public SafetyCenterEntry createFromParcel(Parcel in) {
- return new Builder(in.readString())
- .setTitle(TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in))
- .setSummary(TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in))
- .setSeverityLevel(in.readInt())
- .setSeverityUnspecifiedIconType(in.readInt())
- .setEnabled(in.readBoolean())
- .setPendingIntent(
- in.readParcelable(
- PendingIntent.class.getClassLoader(), PendingIntent.class))
- .setIconAction(
- in.readParcelable(
- IconAction.class.getClassLoader(), IconAction.class))
- .build();
- }
-
- @Override
- public SafetyCenterEntry[] newArray(int size) {
- return new SafetyCenterEntry[size];
- }
- };
-
/** Builder class for {@link SafetyCenterEntry}. */
public static final class Builder {
+
@NonNull
private String mId;
+ @NonNull
private CharSequence mTitle;
+ @Nullable
private CharSequence mSummary;
@EntrySeverityLevel
private int mSeverityLevel = ENTRY_SEVERITY_LEVEL_UNKNOWN;
@SeverityUnspecifiedIconType
private int mSeverityUnspecifiedIconType = SEVERITY_UNSPECIFIED_ICON_TYPE_NO_ICON;
private boolean mEnabled = true;
+ @Nullable
private PendingIntent mPendingIntent;
+ @Nullable
private IconAction mIconAction;
/**
* Creates a {@link Builder} for a {@link SafetyCenterEntry}.
*
- * @param id an encoded string ID to be returned by {@link #getId()}
+ * @param id a unique encoded string ID, see {@link #getId()} for details
+ * @param title a title that describes this entry
*/
- public Builder(@NonNull String id) {
+ public Builder(@NonNull String id, @NonNull CharSequence title) {
mId = requireNonNull(id);
+ mTitle = requireNonNull(title);
}
- /**
- * Creates a pre-populated {@link Builder} with the values from the given {@link
- * SafetyCenterEntry}.
- */
+ /** Creates a {@link Builder} with the values from the given {@link SafetyCenterEntry}. */
public Builder(@NonNull SafetyCenterEntry safetyCenterEntry) {
mId = safetyCenterEntry.mId;
mTitle = safetyCenterEntry.mTitle;
@@ -331,14 +353,14 @@ public final class SafetyCenterEntry implements Parcelable {
mIconAction = safetyCenterEntry.mIconAction;
}
- /** Sets the ID for this entry. Required. */
+ /** Sets the ID for this entry. */
@NonNull
public Builder setId(@NonNull String id) {
mId = requireNonNull(id);
return this;
}
- /** Sets the title for this entry. Required. */
+ /** Sets the title for this entry. */
@NonNull
public Builder setTitle(@NonNull CharSequence title) {
mTitle = requireNonNull(title);
@@ -373,17 +395,17 @@ public final class SafetyCenterEntry implements Parcelable {
return this;
}
- /** Sets whether or not this entry is enabled. Defaults to {@code true}. */
+ /** Sets whether this entry is enabled. Defaults to {@code true}. */
@NonNull
public Builder setEnabled(boolean enabled) {
mEnabled = enabled;
return this;
}
- /** Sets the {@link PendingIntent} to execute when this entry is selected. Required. */
+ /** Sets the optional {@link PendingIntent} to execute when this entry is selected. */
@NonNull
- public Builder setPendingIntent(@NonNull PendingIntent pendingIntent) {
- mPendingIntent = requireNonNull(pendingIntent);
+ public Builder setPendingIntent(@Nullable PendingIntent pendingIntent) {
+ mPendingIntent = pendingIntent;
return this;
}
@@ -420,18 +442,6 @@ public final class SafetyCenterEntry implements Parcelable {
/** An optional additional action with an icon for a {@link SafetyCenterEntry}. */
public static final class IconAction implements Parcelable {
- /**
- * All possible icon action types.
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = "ICON_ACTION_TYPE_", value = {
- ICON_ACTION_TYPE_GEAR,
- ICON_ACTION_TYPE_INFO,
- })
- public @interface IconActionType {
- }
-
/** A gear-type icon action, e.g. that links to a settings page for a specific entry. */
public static final int ICON_ACTION_TYPE_GEAR = 30100;
@@ -441,6 +451,37 @@ public final class SafetyCenterEntry implements Parcelable {
*/
public static final int ICON_ACTION_TYPE_INFO = 30200;
+ /**
+ * All possible icon action types.
+ *
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(
+ prefix = "ICON_ACTION_TYPE_",
+ value = {
+ ICON_ACTION_TYPE_GEAR,
+ ICON_ACTION_TYPE_INFO,
+ })
+ public @interface IconActionType {
+ }
+
+ @NonNull
+ public static final Creator<IconAction> CREATOR =
+ new Creator<IconAction>() {
+ @Override
+ public IconAction createFromParcel(Parcel in) {
+ int type = in.readInt();
+ PendingIntent pendingIntent = in.readTypedObject(PendingIntent.CREATOR);
+ return new IconAction(type, pendingIntent);
+ }
+
+ @Override
+ public IconAction[] newArray(int size) {
+ return new IconAction[size];
+ }
+ };
+
@IconActionType
private final int mType;
@NonNull
@@ -467,7 +508,7 @@ public final class SafetyCenterEntry implements Parcelable {
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (!(o instanceof IconAction)) return false;
IconAction that = (IconAction) o;
return mType == that.mType && Objects.equals(mPendingIntent, that.mPendingIntent);
}
@@ -480,8 +521,10 @@ public final class SafetyCenterEntry implements Parcelable {
@Override
public String toString() {
return "IconAction{"
- + "mType=" + mType
- + ", mPendingIntent=" + mPendingIntent
+ + "mType="
+ + mType
+ + ", mPendingIntent="
+ + mPendingIntent
+ '}';
}
@@ -493,25 +536,7 @@ public final class SafetyCenterEntry implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mType);
- dest.writeParcelable(mPendingIntent, flags);
+ dest.writeTypedObject(mPendingIntent, flags);
}
-
- @NonNull
- public static final Creator<IconAction> CREATOR = new Creator<IconAction>() {
- @Override
- public IconAction createFromParcel(Parcel in) {
- return new IconAction(
- in.readInt(),
- in.readParcelable(
- PendingIntent.class.getClassLoader(), PendingIntent.class));
- }
-
- @Override
- public IconAction[] newArray(int size) {
- return new IconAction[size];
- }
- };
-
}
-
}
diff --git a/framework-s/java/android/safetycenter/SafetyCenterEntryGroup.java b/framework-s/java/android/safetycenter/SafetyCenterEntryGroup.java
index e7f11edf7..652205394 100644
--- a/framework-s/java/android/safetycenter/SafetyCenterEntryGroup.java
+++ b/framework-s/java/android/safetycenter/SafetyCenterEntryGroup.java
@@ -18,6 +18,7 @@ package android.safetycenter;
import static android.os.Build.VERSION_CODES.TIRAMISU;
+import static java.util.Collections.unmodifiableList;
import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
@@ -43,6 +44,27 @@ import java.util.Objects;
public final class SafetyCenterEntryGroup implements Parcelable {
@NonNull
+ public static final Creator<SafetyCenterEntryGroup> CREATOR =
+ new Creator<SafetyCenterEntryGroup>() {
+ @Override
+ public SafetyCenterEntryGroup createFromParcel(Parcel in) {
+ String id = in.readString();
+ CharSequence title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ return new Builder(id, title)
+ .setSummary(TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in))
+ .setSeverityLevel(in.readInt())
+ .setSeverityUnspecifiedIconType(in.readInt())
+ .setEntries(in.createTypedArrayList(SafetyCenterEntry.CREATOR))
+ .build();
+ }
+
+ @Override
+ public SafetyCenterEntryGroup[] newArray(int size) {
+ return new SafetyCenterEntryGroup[size];
+ }
+ };
+
+ @NonNull
private final String mId;
@NonNull
private final CharSequence mTitle;
@@ -62,12 +84,12 @@ public final class SafetyCenterEntryGroup implements Parcelable {
@SafetyCenterEntry.EntrySeverityLevel int severityLevel,
@SafetyCenterEntry.SeverityUnspecifiedIconType int severityUnspecifiedIconType,
@NonNull List<SafetyCenterEntry> entries) {
- mId = requireNonNull(id);
- mTitle = requireNonNull(title);
+ mId = id;
+ mTitle = title;
mSummary = summary;
mSeverityLevel = severityLevel;
mSeverityUnspecifiedIconType = severityUnspecifiedIconType;
- mEntries = new ArrayList<>(entries);
+ mEntries = entries;
}
/**
@@ -108,13 +130,13 @@ public final class SafetyCenterEntryGroup implements Parcelable {
/** Returns the entries that comprise this entry group. */
@NonNull
public List<SafetyCenterEntry> getEntries() {
- return new ArrayList<>(mEntries);
+ return mEntries;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (!(o instanceof SafetyCenterEntryGroup)) return false;
SafetyCenterEntryGroup that = (SafetyCenterEntryGroup) o;
return mSeverityLevel == that.mSeverityLevel
&& mSeverityUnspecifiedIconType == that.mSeverityUnspecifiedIconType
@@ -126,19 +148,26 @@ public final class SafetyCenterEntryGroup implements Parcelable {
@Override
public int hashCode() {
- return Objects.hash(mId, mTitle, mSummary, mSeverityLevel, mSeverityUnspecifiedIconType,
- mEntries);
+ return Objects.hash(
+ mId, mTitle, mSummary, mSeverityLevel, mSeverityUnspecifiedIconType, mEntries);
}
@Override
public String toString() {
return "SafetyCenterEntryGroup{"
- + "mId='" + mId + '\''
- + ", mTitle=" + mTitle
- + ", mSummary=" + mSummary
- + ", mSeverityLevel=" + mSeverityLevel
- + ", mSeverityUnspecifiedIconType=" + mSeverityUnspecifiedIconType
- + ", mEntries=" + mEntries
+ + "mId='"
+ + mId
+ + '\''
+ + ", mTitle="
+ + mTitle
+ + ", mSummary="
+ + mSummary
+ + ", mSeverityLevel="
+ + mSeverityLevel
+ + ", mSeverityUnspecifiedIconType="
+ + mSeverityUnspecifiedIconType
+ + ", mEntries="
+ + mEntries
+ '}';
}
@@ -157,52 +186,36 @@ public final class SafetyCenterEntryGroup implements Parcelable {
dest.writeTypedList(mEntries);
}
- @NonNull
- public static final Creator<SafetyCenterEntryGroup> CREATOR =
- new Creator<SafetyCenterEntryGroup>() {
- @Override
- public SafetyCenterEntryGroup createFromParcel(Parcel in) {
- return new SafetyCenterEntryGroup.Builder(in.readString())
- .setTitle(TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in))
- .setSummary(TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in))
- .setSeverityLevel(in.readInt())
- .setSeverityUnspecifiedIconType(in.readInt())
- .setEntries(in.createTypedArrayList(SafetyCenterEntry.CREATOR))
- .build();
- }
-
- @Override
- public SafetyCenterEntryGroup[] newArray(int size) {
- return new SafetyCenterEntryGroup[size];
- }
- };
-
/** Builder class for {@link SafetyCenterEntryGroup} */
public static final class Builder {
+
+ @NonNull
private String mId;
+ @NonNull
private CharSequence mTitle;
+ @Nullable
private CharSequence mSummary;
@SafetyCenterEntry.EntrySeverityLevel
private int mSeverityLevel = SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_UNKNOWN;
@SafetyCenterEntry.SeverityUnspecifiedIconType
private int mSeverityUnspecifiedIconType =
SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_NO_ICON;
- private List<SafetyCenterEntry> mEntries;
+ @NonNull
+ private List<SafetyCenterEntry> mEntries = new ArrayList<>();
/**
* Creates a {@link Builder} for a {@link SafetyCenterEntryGroup}.
*
- * @param id An encoded string ID that uniquely identifies this
- * {@link SafetyCenterEntryGroup} among all other entry groups in a given Safety
- * Center.
+ * @param id a unique encoded string ID, see {@link #getId} for details
+ * @param title a title for this group of entries
*/
- public Builder(@NonNull String id) {
+ public Builder(@NonNull String id, @NonNull CharSequence title) {
mId = requireNonNull(id);
+ mTitle = requireNonNull(title);
}
/**
- * Creates a pre-populated {@link Builder} with the values from the given {@link
- * SafetyCenterEntryGroup}.
+ * Creates a {@link Builder} with the values from the given {@link SafetyCenterEntryGroup}.
*/
public Builder(@NonNull SafetyCenterEntryGroup safetyCenterEntryGroup) {
mId = safetyCenterEntryGroup.mId;
@@ -213,14 +226,14 @@ public final class SafetyCenterEntryGroup implements Parcelable {
mEntries = new ArrayList<>(safetyCenterEntryGroup.mEntries);
}
- /** Sets the ID for this entry group. Required. */
+ /** Sets the ID for this entry group. */
@NonNull
public Builder setId(@NonNull String id) {
mId = requireNonNull(id);
return this;
}
- /** Sets the title for this entry group. Required. */
+ /** Sets the title for this entry group. */
@NonNull
public Builder setTitle(@NonNull CharSequence title) {
mTitle = requireNonNull(title);
@@ -256,8 +269,8 @@ public final class SafetyCenterEntryGroup implements Parcelable {
}
/**
- * Sets the list of {@link SafetyCenterEntry} contained by this entry group. Defaults to
- * an empty list.
+ * Sets the list of {@link SafetyCenterEntry} contained by this entry group. Defaults to an
+ * empty list.
*/
@NonNull
public Builder setEntries(@NonNull List<SafetyCenterEntry> entries) {
@@ -269,7 +282,8 @@ public final class SafetyCenterEntryGroup implements Parcelable {
@NonNull
public SafetyCenterEntryGroup build() {
return new SafetyCenterEntryGroup(
- mId, mTitle, mSummary, mSeverityLevel, mSeverityUnspecifiedIconType, mEntries);
+ mId, mTitle, mSummary, mSeverityLevel, mSeverityUnspecifiedIconType,
+ unmodifiableList(new ArrayList<>(mEntries)));
}
}
}
diff --git a/framework-s/java/android/safetycenter/SafetyCenterEntryOrGroup.java b/framework-s/java/android/safetycenter/SafetyCenterEntryOrGroup.java
index be0be379e..f4fe145b1 100644
--- a/framework-s/java/android/safetycenter/SafetyCenterEntryOrGroup.java
+++ b/framework-s/java/android/safetycenter/SafetyCenterEntryOrGroup.java
@@ -31,8 +31,8 @@ import androidx.annotation.RequiresApi;
import java.util.Objects;
/**
- * Contains either a single {@link SafetyCenterEntry} or a group of them in a
- * {@link SafetyCenterEntryGroup}.
+ * Contains either a single {@link SafetyCenterEntry} or a group of them in a {@link
+ * SafetyCenterEntryGroup}.
*
* @hide
*/
@@ -40,6 +40,25 @@ import java.util.Objects;
@RequiresApi(TIRAMISU)
public final class SafetyCenterEntryOrGroup implements Parcelable {
+ @NonNull
+ public static final Creator<SafetyCenterEntryOrGroup> CREATOR =
+ new Creator<SafetyCenterEntryOrGroup>() {
+ @Override
+ public SafetyCenterEntryOrGroup createFromParcel(Parcel in) {
+ SafetyCenterEntry maybeEntry = in.readTypedObject(SafetyCenterEntry.CREATOR);
+ SafetyCenterEntryGroup maybeEntryGroup =
+ in.readTypedObject(SafetyCenterEntryGroup.CREATOR);
+ return maybeEntry != null
+ ? new SafetyCenterEntryOrGroup(maybeEntry)
+ : new SafetyCenterEntryOrGroup(maybeEntryGroup);
+ }
+
+ @Override
+ public SafetyCenterEntryOrGroup[] newArray(int size) {
+ return new SafetyCenterEntryOrGroup[size];
+ }
+ };
+
@Nullable
private final SafetyCenterEntry mEntry;
@Nullable
@@ -81,10 +100,9 @@ public final class SafetyCenterEntryOrGroup implements Parcelable {
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (!(o instanceof SafetyCenterEntryOrGroup)) return false;
SafetyCenterEntryOrGroup that = (SafetyCenterEntryOrGroup) o;
- return Objects.equals(mEntry, that.mEntry)
- && Objects.equals(mEntryGroup, that.mEntryGroup);
+ return Objects.equals(mEntry, that.mEntry) && Objects.equals(mEntryGroup, that.mEntryGroup);
}
@Override
@@ -95,8 +113,10 @@ public final class SafetyCenterEntryOrGroup implements Parcelable {
@Override
public String toString() {
return "SafetyCenterEntryOrGroup{"
- + "mEntry=" + mEntry
- + ", mEntryGroup=" + mEntryGroup
+ + "mEntry="
+ + mEntry
+ + ", mEntryGroup="
+ + mEntryGroup
+ '}';
}
@@ -107,33 +127,7 @@ public final class SafetyCenterEntryOrGroup implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeParcelable(mEntry, flags);
- dest.writeParcelable(mEntryGroup, flags);
+ dest.writeTypedObject(mEntry, flags);
+ dest.writeTypedObject(mEntryGroup, flags);
}
-
- @NonNull
- public static final Creator<SafetyCenterEntryOrGroup> CREATOR =
- new Creator<SafetyCenterEntryOrGroup>() {
- @Override
- public SafetyCenterEntryOrGroup createFromParcel(Parcel in) {
- SafetyCenterEntry maybeEntry =
- in.readParcelable(
- SafetyCenterEntry.class.getClassLoader(),
- SafetyCenterEntry.class);
- SafetyCenterEntryGroup maybeEntryGroup =
- in.readParcelable(
- SafetyCenterEntryGroup.class.getClassLoader(),
- SafetyCenterEntryGroup.class);
-
- return maybeEntry != null
- ? new SafetyCenterEntryOrGroup(maybeEntry)
- : new SafetyCenterEntryOrGroup(maybeEntryGroup);
- }
-
- @Override
- public SafetyCenterEntryOrGroup[] newArray(int size) {
- return new SafetyCenterEntryOrGroup[size];
- }
- };
-
}
diff --git a/framework-s/java/android/safetycenter/SafetyCenterErrorDetails.java b/framework-s/java/android/safetycenter/SafetyCenterErrorDetails.java
index 99dbc0151..4c1bd7b77 100644
--- a/framework-s/java/android/safetycenter/SafetyCenterErrorDetails.java
+++ b/framework-s/java/android/safetycenter/SafetyCenterErrorDetails.java
@@ -18,6 +18,8 @@ package android.safetycenter;
import static android.os.Build.VERSION_CODES.TIRAMISU;
+import static java.util.Objects.requireNonNull;
+
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Parcel;
@@ -38,11 +40,27 @@ import java.util.Objects;
public final class SafetyCenterErrorDetails implements Parcelable {
@NonNull
+ public static final Creator<SafetyCenterErrorDetails> CREATOR =
+ new Creator<SafetyCenterErrorDetails>() {
+ @Override
+ public SafetyCenterErrorDetails createFromParcel(Parcel in) {
+ CharSequence errorMessage = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(
+ in);
+ return new SafetyCenterErrorDetails(errorMessage);
+ }
+
+ @Override
+ public SafetyCenterErrorDetails[] newArray(int size) {
+ return new SafetyCenterErrorDetails[0];
+ }
+ };
+
+ @NonNull
private final CharSequence mErrorMessage;
/** Creates a {@link SafetyCenterErrorDetails} with a given error message. */
public SafetyCenterErrorDetails(@NonNull CharSequence errorMessage) {
- mErrorMessage = errorMessage;
+ mErrorMessage = requireNonNull(errorMessage);
}
/** Returns an error message to display to the user. */
@@ -54,7 +72,7 @@ public final class SafetyCenterErrorDetails implements Parcelable {
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (!(o instanceof SafetyCenterErrorDetails)) return false;
SafetyCenterErrorDetails that = (SafetyCenterErrorDetails) o;
return TextUtils.equals(mErrorMessage, that.mErrorMessage);
}
@@ -67,7 +85,8 @@ public final class SafetyCenterErrorDetails implements Parcelable {
@Override
public String toString() {
return "SafetyCenterErrorDetails{"
- + "mErrorMessage=" + mErrorMessage
+ + "mErrorMessage="
+ + mErrorMessage
+ '}';
}
@@ -80,19 +99,4 @@ public final class SafetyCenterErrorDetails implements Parcelable {
public void writeToParcel(@NonNull Parcel dest, int flags) {
TextUtils.writeToParcel(mErrorMessage, dest, flags);
}
-
- @NonNull
- public static final Creator<SafetyCenterErrorDetails> CREATOR =
- new Creator<SafetyCenterErrorDetails>() {
- @Override
- public SafetyCenterErrorDetails createFromParcel(Parcel in) {
- return new SafetyCenterErrorDetails(
- TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in));
- }
-
- @Override
- public SafetyCenterErrorDetails[] newArray(int size) {
- return new SafetyCenterErrorDetails[0];
- }
- };
}
diff --git a/framework-s/java/android/safetycenter/SafetyCenterFrameworkInitializer.java b/framework-s/java/android/safetycenter/SafetyCenterFrameworkInitializer.java
index 1d22b1d5d..aa80595d5 100644
--- a/framework-s/java/android/safetycenter/SafetyCenterFrameworkInitializer.java
+++ b/framework-s/java/android/safetycenter/SafetyCenterFrameworkInitializer.java
@@ -32,20 +32,23 @@ import androidx.annotation.RequiresApi;
@RequiresApi(TIRAMISU)
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public final class SafetyCenterFrameworkInitializer {
+
private SafetyCenterFrameworkInitializer() {
}
/**
- * Called by {@link SystemServiceRegistry}'s static initializer and registers
- * {@link SafetyCenterManager} to {@link Context}, so that {@link Context#getSystemService} can
- * return it.
+ * Called by {@link SystemServiceRegistry}'s static initializer and registers {@link
+ * SafetyCenterManager} to {@link Context}, so that {@link Context#getSystemService} can return
+ * it.
*
* <p>If this is called from other places, it throws a {@link IllegalStateException}.
*/
public static void registerServiceWrappers() {
- SystemServiceRegistry.registerContextAwareService(Context.SAFETY_CENTER_SERVICE,
+ SystemServiceRegistry.registerContextAwareService(
+ Context.SAFETY_CENTER_SERVICE,
SafetyCenterManager.class,
- (context, serviceBinder) -> new SafetyCenterManager(context,
- ISafetyCenterManager.Stub.asInterface(serviceBinder)));
+ (context, serviceBinder) ->
+ new SafetyCenterManager(context,
+ ISafetyCenterManager.Stub.asInterface(serviceBinder)));
}
}
diff --git a/framework-s/java/android/safetycenter/SafetyCenterIssue.java b/framework-s/java/android/safetycenter/SafetyCenterIssue.java
index 3371bc852..a6ab538e0 100644
--- a/framework-s/java/android/safetycenter/SafetyCenterIssue.java
+++ b/framework-s/java/android/safetycenter/SafetyCenterIssue.java
@@ -18,6 +18,7 @@ package android.safetycenter;
import static android.os.Build.VERSION_CODES.TIRAMISU;
+import static java.util.Collections.unmodifiableList;
import static java.util.Objects.requireNonNull;
import android.annotation.IntDef;
@@ -55,31 +56,56 @@ import java.util.Objects;
@RequiresApi(TIRAMISU)
public final class SafetyCenterIssue implements Parcelable {
+ /** Indicates that this is low-severity, and informational. */
+ public static final int ISSUE_SEVERITY_LEVEL_OK = 2100;
+
+ /** Indicates that this issue describes a safety recommendation. */
+ public static final int ISSUE_SEVERITY_LEVEL_RECOMMENDATION = 2200;
+
+ /** Indicates that this issue describes a critical safety warning. */
+ public static final int ISSUE_SEVERITY_LEVEL_CRITICAL_WARNING = 2300;
+
/**
* All possible severity levels for a {@link SafetyCenterIssue}.
*
+ * @hide
* @see SafetyCenterIssue#getSeverityLevel()
* @see Builder#setSeverityLevel(int)
- *
- * @hide
*/
@Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = "ISSUE_SEVERITY_LEVEL_", value = {
- ISSUE_SEVERITY_LEVEL_OK,
- ISSUE_SEVERITY_LEVEL_RECOMMENDATION,
- ISSUE_SEVERITY_LEVEL_CRITICAL_WARNING,
- })
+ @IntDef(
+ prefix = "ISSUE_SEVERITY_LEVEL_",
+ value = {
+ ISSUE_SEVERITY_LEVEL_OK,
+ ISSUE_SEVERITY_LEVEL_RECOMMENDATION,
+ ISSUE_SEVERITY_LEVEL_CRITICAL_WARNING,
+ })
public @interface IssueSeverityLevel {
}
- /** Indicates that this is low-severity, and informational. */
- public static final int ISSUE_SEVERITY_LEVEL_OK = 2100;
-
- /** Indicates that this issue describes a safety recommendation. */
- public static final int ISSUE_SEVERITY_LEVEL_RECOMMENDATION = 2200;
-
- /** Indicates that this issue describes a critical safety warning. */
- public static final int ISSUE_SEVERITY_LEVEL_CRITICAL_WARNING = 2300;
+ @NonNull
+ public static final Creator<SafetyCenterIssue> CREATOR =
+ new Creator<SafetyCenterIssue>() {
+ @Override
+ public SafetyCenterIssue createFromParcel(Parcel in) {
+ String id = in.readString();
+ CharSequence title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ CharSequence subtitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ CharSequence summary = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ return new Builder(id, title, summary)
+ .setSubtitle(subtitle)
+ .setSeverityLevel(in.readInt())
+ .setDismissible(in.readBoolean())
+ .setShouldConfirmDismissal(in.readBoolean())
+ .setActions(in.createTypedArrayList(Action.CREATOR))
+ .build();
+ }
+
+ @Override
+ public SafetyCenterIssue[] newArray(int size) {
+ return new SafetyCenterIssue[size];
+ }
+ };
@NonNull
private final String mId;
@@ -112,7 +138,7 @@ public final class SafetyCenterIssue implements Parcelable {
mSeverityLevel = severityLevel;
mDismissible = isDismissible;
mShouldConfirmDismissal = shouldConfirmDismissal;
- mActions = new ArrayList<>(actions);
+ mActions = actions;
}
/**
@@ -166,13 +192,13 @@ public final class SafetyCenterIssue implements Parcelable {
*/
@NonNull
public List<Action> getActions() {
- return new ArrayList<>(mActions);
+ return mActions;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (!(o instanceof SafetyCenterIssue)) return false;
SafetyCenterIssue that = (SafetyCenterIssue) o;
return mSeverityLevel == that.mSeverityLevel
&& mDismissible == that.mDismissible
@@ -186,21 +212,37 @@ public final class SafetyCenterIssue implements Parcelable {
@Override
public int hashCode() {
- return Objects.hash(mId, mTitle, mSubtitle, mSummary, mSeverityLevel, mDismissible,
- mShouldConfirmDismissal, mActions);
+ return Objects.hash(
+ mId,
+ mTitle,
+ mSubtitle,
+ mSummary,
+ mSeverityLevel,
+ mDismissible,
+ mShouldConfirmDismissal,
+ mActions);
}
@Override
public String toString() {
return "SafetyCenterIssue{"
- + "mId='" + mId + '\''
- + ", mTitle=" + mTitle
- + ", mSubtitle=" + mSubtitle
- + ", mSummary=" + mSummary
- + ", mSeverityLevel=" + mSeverityLevel
- + ", mDismissible=" + mDismissible
- + ", mConfirmDismissal=" + mShouldConfirmDismissal
- + ", mActions=" + mActions
+ + "mId='"
+ + mId
+ + '\''
+ + ", mTitle="
+ + mTitle
+ + ", mSubtitle="
+ + mSubtitle
+ + ", mSummary="
+ + mSummary
+ + ", mSeverityLevel="
+ + mSeverityLevel
+ + ", mDismissible="
+ + mDismissible
+ + ", mConfirmDismissal="
+ + mShouldConfirmDismissal
+ + ", mActions="
+ + mActions
+ '}';
}
@@ -221,34 +263,17 @@ public final class SafetyCenterIssue implements Parcelable {
dest.writeTypedList(mActions);
}
- @NonNull
- public static final Creator<SafetyCenterIssue> CREATOR = new Creator<SafetyCenterIssue>() {
- @Override
- public SafetyCenterIssue createFromParcel(Parcel in) {
- return new Builder(in.readString())
- .setTitle(TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in))
- .setSubtitle(TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in))
- .setSummary(TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in))
- .setSeverityLevel(in.readInt())
- .setDismissible(in.readBoolean())
- .setShouldConfirmDismissal(in.readBoolean())
- .setActions(in.createTypedArrayList(Action.CREATOR))
- .build();
- }
-
- @Override
- public SafetyCenterIssue[] newArray(int size) {
- return new SafetyCenterIssue[size];
- }
- };
-
/** Builder class for {@link SafetyCenterIssue}. */
public static final class Builder {
+
@NonNull
private String mId;
+ @NonNull
private CharSequence mTitle;
- private CharSequence mSubtitle;
+ @NonNull
private CharSequence mSummary;
+ @Nullable
+ private CharSequence mSubtitle;
@IssueSeverityLevel
private int mSeverityLevel = ISSUE_SEVERITY_LEVEL_OK;
private boolean mDismissible = true;
@@ -258,12 +283,18 @@ public final class SafetyCenterIssue implements Parcelable {
/**
* Creates a {@link Builder} for a {@link SafetyCenterIssue}.
*
- * @param id an encoded string ID to be returned by {@link #getId()}
+ * @param id a unique encoded string ID, see {@link #getId()} for details
+ * @param title a title that describes this issue
+ * @param summary a summary of this issue
*/
- public Builder(@NonNull String id) {
+ public Builder(@NonNull String id, @NonNull CharSequence title,
+ @NonNull CharSequence summary) {
mId = requireNonNull(id);
+ mTitle = requireNonNull(title);
+ mSummary = requireNonNull(summary);
}
+ /** Creates a {@link Builder} with the values from the given {@link SafetyCenterIssue}. */
public Builder(@NonNull SafetyCenterIssue issue) {
mId = issue.mId;
mTitle = issue.mTitle;
@@ -275,14 +306,14 @@ public final class SafetyCenterIssue implements Parcelable {
mActions = new ArrayList<>(issue.mActions);
}
- /** Sets the ID for this issue. Required. */
+ /** Sets the ID for this issue. */
@NonNull
public Builder setId(@NonNull String id) {
mId = requireNonNull(id);
return this;
}
- /** Sets the title for this issue. Required. */
+ /** Sets the title for this issue. */
@NonNull
public Builder setTitle(@NonNull CharSequence title) {
mTitle = requireNonNull(title);
@@ -296,7 +327,7 @@ public final class SafetyCenterIssue implements Parcelable {
return this;
}
- /** Sets the summary for this issue. Required. */
+ /** Sets the summary for this issue. */
@NonNull
public Builder setSummary(@NonNull CharSequence summary) {
mSummary = requireNonNull(summary);
@@ -313,7 +344,7 @@ public final class SafetyCenterIssue implements Parcelable {
return this;
}
- /** Sets whether or not this issue can be dismissed. Defaults to {@code true}. */
+ /** Sets whether this issue can be dismissed. Defaults to {@code true}. */
@NonNull
public Builder setDismissible(boolean dismissible) {
mDismissible = dismissible;
@@ -321,8 +352,7 @@ public final class SafetyCenterIssue implements Parcelable {
}
/**
- * Sets whether or not this issue should have its dismissal confirmed. Defaults to {@code
- * true}.
+ * Sets whether this issue should have its dismissal confirmed. Defaults to {@code true}.
*/
@NonNull
public Builder setShouldConfirmDismissal(boolean confirmDismissal) {
@@ -351,7 +381,7 @@ public final class SafetyCenterIssue implements Parcelable {
mSeverityLevel,
mDismissible,
mShouldConfirmDismissal,
- mActions);
+ unmodifiableList(new ArrayList<>(mActions)));
}
}
@@ -365,6 +395,29 @@ public final class SafetyCenterIssue implements Parcelable {
*/
@SystemApi
public static final class Action implements Parcelable {
+
+ @NonNull
+ public static final Creator<Action> CREATOR =
+ new Creator<Action>() {
+ @Override
+ public Action createFromParcel(Parcel in) {
+ String id = in.readString();
+ CharSequence label = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ PendingIntent pendingIntent = in.readTypedObject(PendingIntent.CREATOR);
+ return new Builder(id, label, pendingIntent)
+ .setWillResolve(in.readBoolean())
+ .setIsInFlight(in.readBoolean())
+ .setSuccessMessage(
+ TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in))
+ .build();
+ }
+
+ @Override
+ public Action[] newArray(int size) {
+ return new Action[size];
+ }
+ };
+
@NonNull
private final String mId;
@NonNull
@@ -410,18 +463,18 @@ public final class SafetyCenterIssue implements Parcelable {
}
/**
- * Returns whether invoking this action will fix or address the issue sufficiently for it
- * to be considered resolved (i.e. the issue will no longer need to be conveyed to the user
- * in the UI).
+ * Returns whether invoking this action will fix or address the issue sufficiently for it to
+ * be considered resolved (i.e. the issue will no longer need to be conveyed to the user in
+ * the UI).
*/
public boolean willResolve() {
return mWillResolve;
}
/**
- * Returns whether or not this action is currently being executed (i.e. the user clicked
- * on a button that triggered this action, and now the Safety Center is waiting for the
- * action's result).
+ * Returns whether this action is currently being executed (i.e. the user clicked on a
+ * button that triggered this action, and now the Safety Center is waiting for the action's
+ * result).
*/
public boolean isInFlight() {
return mInFlight;
@@ -439,7 +492,7 @@ public final class SafetyCenterIssue implements Parcelable {
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (!(o instanceof Action)) return false;
Action action = (Action) o;
return Objects.equals(mId, action.mId)
&& TextUtils.equals(mLabel, action.mLabel)
@@ -451,19 +504,25 @@ public final class SafetyCenterIssue implements Parcelable {
@Override
public int hashCode() {
- return Objects.hash(
- mId, mLabel, mSuccessMessage, mWillResolve, mInFlight, mPendingIntent);
+ return Objects.hash(mId, mLabel, mSuccessMessage, mWillResolve, mInFlight,
+ mPendingIntent);
}
@Override
public String toString() {
return "Action{"
- + "mId=" + mId
- + ", mLabel=" + mLabel
- + ", mPendingIntent=" + mPendingIntent
- + ", mWillResolve=" + mWillResolve
- + ", mInFlight=" + mInFlight
- + ", mSuccessMessage=" + mSuccessMessage
+ + "mId="
+ + mId
+ + ", mLabel="
+ + mLabel
+ + ", mPendingIntent="
+ + mPendingIntent
+ + ", mWillResolve="
+ + mWillResolve
+ + ", mInFlight="
+ + mInFlight
+ + ", mSuccessMessage="
+ + mSuccessMessage
+ '}';
}
@@ -476,57 +535,56 @@ public final class SafetyCenterIssue implements Parcelable {
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(mId);
TextUtils.writeToParcel(mLabel, dest, flags);
- dest.writeParcelable(mPendingIntent, flags);
+ dest.writeTypedObject(mPendingIntent, flags);
dest.writeBoolean(mWillResolve);
dest.writeBoolean(mInFlight);
TextUtils.writeToParcel(mSuccessMessage, dest, flags);
}
- @NonNull
- public static final Creator<Action> CREATOR = new Creator<Action>() {
- @Override
- public Action createFromParcel(Parcel in) {
- return new Action.Builder(in.readString())
- .setLabel(TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in))
- .setPendingIntent(
- in.readParcelable(
- PendingIntent.class.getClassLoader(), PendingIntent.class))
- .setWillResolve(in.readBoolean())
- .setIsInFlight(in.readBoolean())
- .setSuccessMessage(TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in))
- .build();
- }
-
- @Override
- public Action[] newArray(int size) {
- return new Action[size];
- }
- };
-
/** Builder class for {@link Action}. */
public static final class Builder {
+
+ @NonNull
private String mId;
+ @NonNull
private CharSequence mLabel;
+ @NonNull
private PendingIntent mPendingIntent;
private boolean mWillResolve;
private boolean mInFlight;
+ @Nullable
private CharSequence mSuccessMessage;
- public Builder(@NonNull String id) {
- mId = id;
+ /**
+ * Creates a new {@link Builder} for an {@link Action}.
+ *
+ * @param id a unique ID for this action
+ * @param label a label describing this action
+ * @param pendingIntent a {@link PendingIntent} to be sent when this action is taken
+ */
+ public Builder(
+ @NonNull String id, @NonNull CharSequence label,
+ @NonNull PendingIntent pendingIntent) {
+ mId = requireNonNull(id);
+ mLabel = requireNonNull(label);
+ mPendingIntent = requireNonNull(pendingIntent);
+ }
+
+ /** Sets the ID of this {@link Action} */
+ @NonNull
+ public Builder setId(@NonNull String id) {
+ mId = requireNonNull(id);
+ return this;
}
- /** Sets the label of this {@link Action}. Required. */
+ /** Sets the label of this {@link Action}. */
@NonNull
public Builder setLabel(@NonNull CharSequence label) {
mLabel = requireNonNull(label);
return this;
}
- /**
- * Sets the {@link PendingIntent} to be sent when this {@link Action} is taken.
- * Required.
- */
+ /** Sets the {@link PendingIntent} to be sent when this {@link Action} is taken. */
@NonNull
public Builder setPendingIntent(@NonNull PendingIntent pendingIntent) {
mPendingIntent = requireNonNull(pendingIntent);
@@ -534,8 +592,8 @@ public final class SafetyCenterIssue implements Parcelable {
}
/**
- * Sets whether or not this action will resolve the issue when executed. Defaults to
- * false.
+ * Sets whether this action will resolve the issue when executed. Defaults to {@code
+ * false}.
*
* @see #willResolve()
*/
@@ -547,9 +605,9 @@ public final class SafetyCenterIssue implements Parcelable {
}
/**
- * Sets a boolean that indicates whether or not this action is currently being executed
- * (i.e. the user clicked on a button that triggered this action, and now the Safety
- * Center is waiting for the action's result). Defaults to false.
+ * Sets a boolean that indicates whether this action is currently being executed (i.e.
+ * the user clicked on a button that triggered this action, and now the Safety Center is
+ * waiting for the action's result). Defaults to {@code false}.
*
* @see #isInFlight()
*/
@@ -573,8 +631,8 @@ public final class SafetyCenterIssue implements Parcelable {
/** Creates the {@link Action} defined by this {@link Builder}. */
@NonNull
public Action build() {
- return new Action(
- mId, mLabel, mPendingIntent, mWillResolve, mInFlight, mSuccessMessage);
+ return new Action(mId, mLabel, mPendingIntent, mWillResolve, mInFlight,
+ mSuccessMessage);
}
}
}
diff --git a/framework-s/java/android/safetycenter/SafetyCenterManager.java b/framework-s/java/android/safetycenter/SafetyCenterManager.java
index 11fc87403..9dfe691d7 100644
--- a/framework-s/java/android/safetycenter/SafetyCenterManager.java
+++ b/framework-s/java/android/safetycenter/SafetyCenterManager.java
@@ -33,6 +33,7 @@ import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
+import android.content.Intent;
import android.os.Binder;
import android.os.RemoteException;
import android.safetycenter.config.SafetyCenterConfig;
@@ -51,11 +52,12 @@ import java.util.concurrent.Executor;
* Interface for communicating with the Safety Center, which consolidates UI for security and
* privacy features on the device.
*
- * These APIs are intended to be used by the following clients:
+ * <p>These APIs are intended to be used by the following clients:
+ *
* <ul>
- * <li>Safety sources represented in Safety Center UI
- * <li>Dependents on the state of Safety Center UI
- * <li>Managers of Safety Center UI
+ * <li>Safety sources represented in Safety Center UI
+ * <li>Dependents on the state of Safety Center UI
+ * <li>Managers of Safety Center UI
* </ul>
*
* @hide
@@ -66,6 +68,30 @@ import java.util.concurrent.Executor;
public final class SafetyCenterManager {
/**
+ * Broadcast Action: A broadcast sent by the system to indicate that the value returned by
+ * {@link SafetyCenterManager#isSafetyCenterEnabled()} has changed.
+ *
+ * <p>This broadcast will inform receivers about changes to {@link
+ * SafetyCenterManager#isSafetyCenterEnabled()}, should they want to check the new value and
+ * enable/disable components accordingly.
+ *
+ * <p>This broadcast is sent explicitly to safety sources by targeting intents to a specified
+ * set of packages in the {@link SafetyCenterConfig}. The receiving components must hold the
+ * {@link android.Manifest.permission#SEND_SAFETY_CENTER_UPDATE} permission, and can use a
+ * manifest-registered receiver to be woken up by Safety Center.
+ *
+ * <p>This broadcast is also sent implicitly system-wide. The receiving components must hold the
+ * {@link android.Manifest.permission#READ_SAFETY_CENTER_STATUS} permission.
+ *
+ * <p>This broadcast is not sent out if the device does not support Safety Center.
+ *
+ * <p class="note">This is a protected intent that can only be sent by the system.
+ */
+ @SdkConstant(BROADCAST_INTENT_ACTION)
+ public static final String ACTION_SAFETY_CENTER_ENABLED_CHANGED =
+ "android.safetycenter.action.SAFETY_CENTER_ENABLED_CHANGED";
+
+ /**
* Broadcast Action: A broadcast sent by the system to indicate that {@link SafetyCenterManager}
* is requesting data from safety sources regarding their safety state.
*
@@ -74,13 +100,14 @@ public final class SafetyCenterManager {
* updated.
*
* <p>This broadcast is sent explicitly to safety sources by targeting intents to a specified
- * set of components provided by the safety sources in the {@link SafetyCenterConfig}.
- * The receiving components should be manifest-declared receivers so that safety sources can be
- * requested to send data even if they are not running.
+ * set of packages provided by the safety sources in the {@link SafetyCenterConfig}. The
+ * receiving components must hold the {@link
+ * android.Manifest.permission#SEND_SAFETY_CENTER_UPDATE} permission, and can use a
+ * manifest-registered receiver to be woken up by Safety Center.
*
* <p>On receiving this broadcast, safety sources should determine their safety state according
- * to the parameters specified in the intent extras (see below) and set {@link SafetySourceData}
- * using {@link #setSafetySourceData}, along with a {@link SafetyEvent} with
+ * to the parameters specified in the intent extras (see below) and set {@link
+ * SafetySourceData} using {@link #setSafetySourceData}, along with a {@link SafetyEvent} with
* {@link SafetyEvent#getType()} set to {@link SafetyEvent#SAFETY_EVENT_TYPE_REFRESH_REQUESTED}
* and {@link SafetyEvent#getRefreshBroadcastId()} set to the value of broadcast intent extra
* {@link #EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID}. If the safety source is unable to provide
@@ -91,18 +118,20 @@ public final class SafetyCenterManager {
* <p class="note">This is a protected intent that can only be sent by the system.
*
* <p>Includes the following extras:
+ *
* <ul>
- * <li>{@link #EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE}: An int representing the type of data
- * being requested. Possible values are {@link #EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA} and
- * {@link #EXTRA_REFRESH_REQUEST_TYPE_GET_DATA}.
- * <li>{@link #EXTRA_REFRESH_SAFETY_SOURCE_IDS}: A {@code String[]} of ids representing the
- * safety sources being requested for data. This extra exists for disambiguation in the case
- * that a single component is responsible for receiving refresh requests for multiple safety
- * sources.
- * <li>{@link #EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID}: An unique identifier for the refresh
- * request broadcast. This extra should be used to specify
- * {@link SafetyEvent#getRefreshBroadcastId()} when the safety source responds to the broadcast
- * using {@link #setSafetySourceData}.
+ * <li>{@link #EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE}: An int representing the type of
+ * data being requested. Possible values are {@link
+ * #EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA} and {@link
+ * #EXTRA_REFRESH_REQUEST_TYPE_GET_DATA}.
+ * <li>{@link #EXTRA_REFRESH_SAFETY_SOURCE_IDS}: A {@code String[]} of ids representing the
+ * safety sources being requested for data. This extra exists for disambiguation in the case
+ * that a single component is responsible for receiving refresh requests for multiple safety
+ * sources.
+ * <li>{@link #EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID}: An unique identifier for the
+ * refresh request broadcast. This extra should be used to specify {@link
+ * SafetyEvent#getRefreshBroadcastId()} when the safety source responds to the broadcast
+ * using {@link #setSafetySourceData}.
* </ul>
*/
@SdkConstant(BROADCAST_INTENT_ACTION)
@@ -110,11 +139,11 @@ public final class SafetyCenterManager {
"android.safetycenter.action.REFRESH_SAFETY_SOURCES";
/**
- * Used as a {@code String[]} extra field in {@link #ACTION_REFRESH_SAFETY_SOURCES}
- * intents to specify the safety source ids of the safety sources being requested for data by
- * Safety Center.
+ * Used as a {@code String[]} extra field in {@link #ACTION_REFRESH_SAFETY_SOURCES} intents to
+ * specify the safety source ids of the safety sources being requested for data by Safety
+ * Center.
*
- * When this extra field is not specified in the intent, it is assumed that Safety Center is
+ * <p>When this extra field is not specified in the intent, it is assumed that Safety Center is
* requesting data from all safety sources supported by the component receiving the broadcast.
*/
public static final String EXTRA_REFRESH_SAFETY_SOURCE_IDS =
@@ -124,32 +153,53 @@ public final class SafetyCenterManager {
* Used as an {@code int} extra field in {@link #ACTION_REFRESH_SAFETY_SOURCES} intents to
* specify the type of data request from Safety Center.
*
- * Possible values are {@link #EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA} and
- * {@link #EXTRA_REFRESH_REQUEST_TYPE_GET_DATA}
+ * <p>Possible values are {@link #EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA} and {@link
+ * #EXTRA_REFRESH_REQUEST_TYPE_GET_DATA}
*/
public static final String EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE =
"android.safetycenter.extra.REFRESH_SAFETY_SOURCES_REQUEST_TYPE";
/**
- * Used as an {@code String} extra field in {@link #ACTION_REFRESH_SAFETY_SOURCES} intents to
+ * Used as a {@code String} extra field in {@link #ACTION_REFRESH_SAFETY_SOURCES} intents to
* specify a string identifier for the broadcast.
*/
public static final String EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID =
"android.safetycenter.extra.REFRESH_SAFETY_SOURCES_BROADCAST_ID";
/**
- * All possible types of data refresh requests in broadcasts with intent action
- * {@link #ACTION_REFRESH_SAFETY_SOURCES}.
+ * Used as a {@code String} extra field in {@link Intent#ACTION_SAFETY_CENTER} intents to
+ * specify an issue ID to redirect to, if applicable.
*
- * @hide
+ * <p>This extra must be used in conjunction with {@link #EXTRA_SAFETY_SOURCE_ID} as an issue
+ * ID does not uniquely identify a {@link SafetySourceIssue}. Otherwise, no redirection will
+ * occur.
*/
- @IntDef(prefix = {"EXTRA_REFRESH_REQUEST_TYPE_"}, value = {
- EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA,
- EXTRA_REFRESH_REQUEST_TYPE_GET_DATA,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface RefreshRequestType {
- }
+ public static final String EXTRA_SAFETY_SOURCE_ISSUE_ID =
+ "android.safetycenter.extra.SAFETY_SOURCE_ISSUE_ID";
+
+ /**
+ * Used as a {@code String} extra field in {@link Intent#ACTION_SAFETY_CENTER} intents to
+ * specify a source ID for the {@link SafetySourceIssue} to redirect to, if applicable.
+ *
+ * <p>This extra must be used in conjunction with {@link #EXTRA_SAFETY_SOURCE_ISSUE_ID}.
+ * Otherwise, no redirection will occur.
+ */
+ public static final String EXTRA_SAFETY_SOURCE_ID =
+ "android.safetycenter.extra.SAFETY_SOURCE_ID";
+
+ /**
+ * Used as a {@link android.os.UserHandle} extra field in {@link Intent#ACTION_SAFETY_CENTER}
+ * intents to specify a user for a given {@link SafetySourceIssue} to redirect to, if
+ * applicable.
+ *
+ * <p>This extra can be used if the same issue ID is created for multiple users (e.g. to
+ * disambiguate personal profile vs. managed profiles issues).
+ *
+ * <p>This extra can be used in conjunction with {@link #EXTRA_SAFETY_SOURCE_ISSUE_ID} and
+ * {@link #EXTRA_SAFETY_SOURCE_ID}. Otherwise, no redirection will occur.
+ */
+ public static final String EXTRA_SAFETY_SOURCE_USER_HANDLE =
+ "android.safetycenter.extra.SAFETY_SOURCE_USER_HANDLE";
/**
* Used as an int value for {@link #EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE} to indicate that
@@ -157,38 +207,36 @@ public final class SafetyCenterManager {
* broadcast with intent action {@link #ACTION_REFRESH_SAFETY_SOURCES} and provide it to Safety
* Center.
*
- * The term "fresh" here means that the sources should ensure that the safety data is accurate
- * as possible at the time of providing it to Safety Center, even if it involves performing an
- * expensive and/or slow process.
+ * <p>The term "fresh" here means that the sources should ensure that the safety data is
+ * accurate as possible at the time of providing it to Safety Center, even if it involves
+ * performing an expensive and/or slow process.
*/
public static final int EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA = 0;
/**
- * Used as an int value for
- * {@link #EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE} to indicate that upon receiving a
- * broadcasts with intent action {@link #ACTION_REFRESH_SAFETY_SOURCES}, the safety source
- * should provide data relating to their safety state to Safety Center.
+ * Used as an int value for {@link #EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE} to indicate that
+ * upon receiving a broadcasts with intent action {@link #ACTION_REFRESH_SAFETY_SOURCES}, the
+ * safety source should provide data relating to their safety state to Safety Center.
*
- * If the source already has its safety data cached, it may provide it without triggering a
+ * <p>If the source already has its safety data cached, it may provide it without triggering a
* process to fetch state which may be expensive and/or slow.
*/
public static final int EXTRA_REFRESH_REQUEST_TYPE_GET_DATA = 1;
/**
- * The reason for requesting a refresh of {@link SafetySourceData} from safety sources.
+ * All possible types of data refresh requests in broadcasts with intent action {@link
+ * #ACTION_REFRESH_SAFETY_SOURCES}.
*
* @hide
*/
- @IntDef(prefix = {"REFRESH_REASON_"}, value = {
- REFRESH_REASON_PAGE_OPEN,
- REFRESH_REASON_RESCAN_BUTTON_CLICK,
- REFRESH_REASON_DEVICE_REBOOT,
- REFRESH_REASON_DEVICE_LOCALE_CHANGE,
- REFRESH_REASON_SAFETY_CENTER_ENABLED,
- REFRESH_REASON_OTHER
- })
+ @IntDef(
+ prefix = {"EXTRA_REFRESH_REQUEST_TYPE_"},
+ value = {
+ EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA,
+ EXTRA_REFRESH_REQUEST_TYPE_GET_DATA,
+ })
@Retention(RetentionPolicy.SOURCE)
- public @interface RefreshReason {
+ public @interface RefreshRequestType {
}
/** Indicates that the Safety Center UI has been opened by the user. */
@@ -209,6 +257,25 @@ public final class SafetyCenterManager {
/** Indicates a generic reason for Safety Center refresh. */
public static final int REFRESH_REASON_OTHER = 600;
+ /**
+ * The reason for requesting a refresh of {@link SafetySourceData} from safety sources.
+ *
+ * @hide
+ */
+ @IntDef(
+ prefix = {"REFRESH_REASON_"},
+ value = {
+ REFRESH_REASON_PAGE_OPEN,
+ REFRESH_REASON_RESCAN_BUTTON_CLICK,
+ REFRESH_REASON_DEVICE_REBOOT,
+ REFRESH_REASON_DEVICE_LOCALE_CHANGE,
+ REFRESH_REASON_SAFETY_CENTER_ENABLED,
+ REFRESH_REASON_OTHER
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface RefreshReason {
+ }
+
/** Listener for changes to {@link SafetyCenterData}. */
public interface OnSafetyCenterDataChangedListener {
@@ -255,10 +322,7 @@ public final class SafetyCenterManager {
* <p>If this returns {@code false}, all the other methods in this class will no-op and/or
* return default values.
*/
- @RequiresPermission(anyOf = {
- READ_SAFETY_CENTER_STATUS,
- SEND_SAFETY_CENTER_UPDATE
- })
+ @RequiresPermission(anyOf = {READ_SAFETY_CENTER_STATUS, SEND_SAFETY_CENTER_UPDATE})
public boolean isSafetyCenterEnabled() {
try {
return mService.isSafetyCenterEnabled();
@@ -268,8 +332,8 @@ public final class SafetyCenterManager {
}
/**
- * Set the latest {@link SafetySourceData} for a safety source, to be displayed in
- * Safety Center UI.
+ * Set the latest {@link SafetySourceData} for a safety source, to be displayed in Safety
+ * Center UI.
*
* <p>Each {@code safetySourceId} uniquely identifies the {@link SafetySourceData} for the
* calling user.
@@ -279,10 +343,10 @@ public final class SafetyCenterManager {
*
* @param safetySourceId the unique identifier for a safety source in the calling user
* @param safetySourceData the latest safety data for the safety source in the calling user. If
- * a safety source does not have any data to set, it can set its
- * {@link SafetySourceData} to {@code null}, in which case Safety Center
- * will fall back to any placeholder data specified in the safety source
- * xml configuration.
+ * a safety source does not have any data to set, it can set its {@link
+ * SafetySourceData} to {@code null}, in which case Safety Center will
+ * fall back to any placeholder data specified in the safety source xml
+ * configuration.
* @param safetyEvent the event that triggered the safety source to set safety data
*/
@RequiresPermission(SEND_SAFETY_CENTER_UPDATE)
@@ -306,8 +370,8 @@ public final class SafetyCenterManager {
}
/**
- * Returns the latest {@link SafetySourceData} set through {@link #setSafetySourceData}
- * for the given {@code safetySourceId} and calling user.
+ * Returns the latest {@link SafetySourceData} set through {@link #setSafetySourceData} for the
+ * given {@code safetySourceId} and calling user.
*
* <p>Returns {@code null} if there never was any data sent for the given {@code safetySourceId}
* and user.
@@ -319,9 +383,7 @@ public final class SafetyCenterManager {
try {
return mService.getSafetySourceData(
- safetySourceId,
- mContext.getPackageName(),
- mContext.getUser().getIdentifier());
+ safetySourceId, mContext.getPackageName(), mContext.getUser().getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -357,10 +419,9 @@ public final class SafetyCenterManager {
/**
* Requests safety sources to set their latest {@link SafetySourceData} for Safety Center.
*
- * <p>This API sends a broadcast to all safety sources with action
- * {@link #ACTION_REFRESH_SAFETY_SOURCES}.
- * See {@link #ACTION_REFRESH_SAFETY_SOURCES} for details on how safety sources should respond
- * to receiving these broadcasts.
+ * <p>This API sends a broadcast to all safety sources with action {@link
+ * #ACTION_REFRESH_SAFETY_SOURCES}. See {@link #ACTION_REFRESH_SAFETY_SOURCES} for details on
+ * how safety sources should respond to receiving these broadcasts.
*
* @param refreshReason the reason for the refresh
*/
@@ -373,6 +434,17 @@ public final class SafetyCenterManager {
}
}
+ /** Returns the current {@link SafetyCenterConfig}, if available. */
+ @RequiresPermission(MANAGE_SAFETY_CENTER)
+ @Nullable
+ public SafetyCenterConfig getSafetyCenterConfig() {
+ try {
+ return mService.getSafetyCenterConfig();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/**
* Returns the current {@link SafetyCenterData}, assembled from {@link SafetySourceData} from
* all sources.
@@ -404,8 +476,8 @@ public final class SafetyCenterManager {
ListenerDelegate delegate = new ListenerDelegate(executor, listener);
try {
- mService.addOnSafetyCenterDataChangedListener(
- delegate, mContext.getUser().getIdentifier());
+ mService.addOnSafetyCenterDataChangedListener(delegate,
+ mContext.getUser().getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -433,6 +505,7 @@ public final class SafetyCenterManager {
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
+ delegate.markAsRemoved();
mListenersToDelegates.remove(listener);
}
}
@@ -448,8 +521,8 @@ public final class SafetyCenterManager {
requireNonNull(safetyCenterIssueId, "safetyCenterIssueId cannot be null");
try {
- mService.dismissSafetyCenterIssue(
- safetyCenterIssueId, mContext.getUser().getIdentifier());
+ mService.dismissSafetyCenterIssue(safetyCenterIssueId,
+ mContext.getUser().getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -465,15 +538,13 @@ public final class SafetyCenterManager {
*/
@RequiresPermission(MANAGE_SAFETY_CENTER)
public void executeSafetyCenterIssueAction(
- @NonNull String safetyCenterIssueId,
- @NonNull String safetyCenterIssueActionId) {
+ @NonNull String safetyCenterIssueId, @NonNull String safetyCenterIssueActionId) {
requireNonNull(safetyCenterIssueId, "safetyCenterIssueId cannot be null");
requireNonNull(safetyCenterIssueActionId, "safetyCenterIssueActionId cannot be null");
try {
mService.executeSafetyCenterIssueAction(
- safetyCenterIssueId,
- safetyCenterIssueActionId,
+ safetyCenterIssueId, safetyCenterIssueActionId,
mContext.getUser().getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -481,64 +552,70 @@ public final class SafetyCenterManager {
}
/**
- * Clears all {@link SafetySourceData} set by safety sources using {@link #setSafetySourceData}.
+ * Clears all {@link SafetySourceData} (set by safety sources using {@link
+ * #setSafetySourceData}) for testing.
*
- * <p>Note: This API serves to facilitate CTS testing and should not be used for other purposes.
+ * <p>Note: This API serves to facilitate CTS testing and should not be used for other
+ * purposes.
*/
@RequiresPermission(MANAGE_SAFETY_CENTER)
- public void clearAllSafetySourceData() {
+ public void clearAllSafetySourceDataForTests() {
try {
- mService.clearAllSafetySourceData();
+ mService.clearAllSafetySourceDataForTests();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
- * Sets an override of the {@link SafetyCenterConfig} set through XML.
+ * Overrides the {@link SafetyCenterConfig} for testing.
*
- * When set, the override {@link SafetyCenterConfig} will be used instead of the
- * {@link SafetyCenterConfig} parsed from the XML file to read configured safety sources.
+ * <p>When set, the overridden {@link SafetyCenterConfig} will be used instead of the {@link
+ * SafetyCenterConfig} parsed from the XML file to read configured safety sources.
*
* <p>Note: This API serves to facilitate CTS testing and should not be used to configure safety
* sources dynamically for production. Once used for testing, the override should be cleared.
*
- * @see #clearSafetyCenterConfigOverride()
+ * @see #clearSafetyCenterConfigForTests()
*/
@RequiresPermission(MANAGE_SAFETY_CENTER)
- public void setSafetyCenterConfigOverride(@NonNull SafetyCenterConfig safetyCenterConfig) {
+ public void setSafetyCenterConfigForTests(@NonNull SafetyCenterConfig safetyCenterConfig) {
requireNonNull(safetyCenterConfig, "safetyCenterConfig cannot be null");
try {
- mService.setSafetyCenterConfigOverride(safetyCenterConfig);
+ mService.setSafetyCenterConfigForTests(safetyCenterConfig);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
- * Clears the override of the {@link SafetyCenterConfig} set through XML.
+ * Clears the override of the {@link SafetyCenterConfig} set for testing.
+ *
+ * <p>Once cleared, the {@link SafetyCenterConfig} parsed from the XML file will be used to read
+ * configured safety sources.
*
* <p>Note: This API serves to facilitate CTS testing and should not be used for other purposes.
*
- * @see #setSafetyCenterConfigOverride(SafetyCenterConfig)
+ * @see #setSafetyCenterConfigForTests(SafetyCenterConfig)
*/
@RequiresPermission(MANAGE_SAFETY_CENTER)
- public void clearSafetyCenterConfigOverride() {
+ public void clearSafetyCenterConfigForTests() {
try {
- mService.clearSafetyCenterConfigOverride();
+ mService.clearSafetyCenterConfigForTests();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
- private static final class ListenerDelegate
- extends IOnSafetyCenterDataChangedListener.Stub {
+ private static final class ListenerDelegate extends IOnSafetyCenterDataChangedListener.Stub {
@NonNull
private final Executor mExecutor;
@NonNull
private final OnSafetyCenterDataChangedListener mOriginalListener;
+ private volatile boolean mRemoved = false;
+
private ListenerDelegate(
@NonNull Executor executor,
@NonNull OnSafetyCenterDataChangedListener originalListener) {
@@ -553,7 +630,16 @@ public final class SafetyCenterManager {
final long identity = Binder.clearCallingIdentity();
try {
mExecutor.execute(
- () -> mOriginalListener.onSafetyCenterDataChanged(safetyCenterData));
+ () -> {
+ if (mRemoved) {
+ return;
+ }
+ // The remove call could still complete at this point, but we're ok
+ // with this raciness on separate threads. If the listener is removed on
+ // the same thread as `mExecutor`; the above check should ensure that
+ // the listener won't be called after the remove call.
+ mOriginalListener.onSafetyCenterDataChanged(safetyCenterData);
+ });
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -565,10 +651,24 @@ public final class SafetyCenterManager {
final long identity = Binder.clearCallingIdentity();
try {
- mExecutor.execute(() -> mOriginalListener.onError(safetyCenterErrorDetails));
+ mExecutor.execute(
+ () -> {
+ if (mRemoved) {
+ return;
+ }
+ // The remove call could still complete at this point, but we're ok
+ // with this raciness on separate threads. If the listener is removed on
+ // the same thread as `mExecutor`; the above check should ensure that
+ // the listener won't be called after the remove call.
+ mOriginalListener.onError(safetyCenterErrorDetails);
+ });
} finally {
Binder.restoreCallingIdentity(identity);
}
}
+
+ public void markAsRemoved() {
+ mRemoved = true;
+ }
}
}
diff --git a/framework-s/java/android/safetycenter/SafetyCenterStaticEntry.java b/framework-s/java/android/safetycenter/SafetyCenterStaticEntry.java
index 8ff76bc29..164b3bf81 100644
--- a/framework-s/java/android/safetycenter/SafetyCenterStaticEntry.java
+++ b/framework-s/java/android/safetycenter/SafetyCenterStaticEntry.java
@@ -45,22 +45,37 @@ import java.util.Objects;
public final class SafetyCenterStaticEntry implements Parcelable {
@NonNull
+ public static final Creator<SafetyCenterStaticEntry> CREATOR =
+ new Creator<SafetyCenterStaticEntry>() {
+ @Override
+ public SafetyCenterStaticEntry createFromParcel(Parcel in) {
+ CharSequence title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ return new SafetyCenterStaticEntry.Builder(title)
+ .setSummary(TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in))
+ .setPendingIntent(in.readTypedObject(PendingIntent.CREATOR))
+ .build();
+ }
+
+ @Override
+ public SafetyCenterStaticEntry[] newArray(int size) {
+ return new SafetyCenterStaticEntry[size];
+ }
+ };
+
+ @NonNull
private final CharSequence mTitle;
@Nullable
private final CharSequence mSummary;
- @NonNull
+ @Nullable
private final PendingIntent mPendingIntent;
- /**
- * Creates a {@link SafetyCenterStaticEntry} with the given title, summary, and pendingIntent
- */
- public SafetyCenterStaticEntry(
+ private SafetyCenterStaticEntry(
@NonNull CharSequence title,
@Nullable CharSequence summary,
- @NonNull PendingIntent pendingIntent) {
- mTitle = requireNonNull(title);
+ @Nullable PendingIntent pendingIntent) {
+ mTitle = title;
mSummary = summary;
- mPendingIntent = requireNonNull(pendingIntent);
+ mPendingIntent = pendingIntent;
}
/** Returns the title that describes this entry. */
@@ -69,14 +84,20 @@ public final class SafetyCenterStaticEntry implements Parcelable {
return mTitle;
}
- /** Returns the summary text that describes this entry if present, or {@code null} otherwise. */
+ /**
+ * Returns the optional summary text that describes this entry if present, or {@code null}
+ * otherwise.
+ */
@Nullable
public CharSequence getSummary() {
return mSummary;
}
- /** Returns the {@link PendingIntent} to execute when this entry is selected. */
- @NonNull
+ /**
+ * Returns the optional {@link PendingIntent} to execute when this entry is selected if present,
+ * or {@code null} otherwise.
+ */
+ @Nullable
public PendingIntent getPendingIntent() {
return mPendingIntent;
}
@@ -84,7 +105,7 @@ public final class SafetyCenterStaticEntry implements Parcelable {
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (!(o instanceof SafetyCenterStaticEntry)) return false;
SafetyCenterStaticEntry that = (SafetyCenterStaticEntry) o;
return TextUtils.equals(mTitle, that.mTitle)
&& TextUtils.equals(mSummary, that.mSummary)
@@ -99,9 +120,12 @@ public final class SafetyCenterStaticEntry implements Parcelable {
@Override
public String toString() {
return "SafetyCenterStaticEntry{"
- + "mTitle=" + mTitle
- + ", mSummary=" + mSummary
- + ", mPendingIntent=" + mPendingIntent
+ + "mTitle="
+ + mTitle
+ + ", mSummary="
+ + mSummary
+ + ", mPendingIntent="
+ + mPendingIntent
+ '}';
}
@@ -114,24 +138,62 @@ public final class SafetyCenterStaticEntry implements Parcelable {
public void writeToParcel(@NonNull Parcel dest, int flags) {
TextUtils.writeToParcel(mTitle, dest, flags);
TextUtils.writeToParcel(mSummary, dest, flags);
- dest.writeParcelable(mPendingIntent, flags);
+ dest.writeTypedObject(mPendingIntent, flags);
}
- @NonNull
- public static final Creator<SafetyCenterStaticEntry> CREATOR =
- new Creator<SafetyCenterStaticEntry>() {
- @Override
- public SafetyCenterStaticEntry createFromParcel(Parcel source) {
- return new SafetyCenterStaticEntry(
- /* title= */ TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source),
- /* summary= */ TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source),
- source.readParcelable(
- PendingIntent.class.getClassLoader(), PendingIntent.class));
+ /** Builder class for {@link SafetyCenterStaticEntry}. */
+ public static final class Builder {
+
+ @NonNull
+ private CharSequence mTitle;
+ @Nullable
+ private CharSequence mSummary;
+ @Nullable
+ private PendingIntent mPendingIntent;
+
+ /**
+ * Creates a {@link Builder} for a {@link SafetyCenterEntry}.
+ *
+ * @param title a title that describes this static entry
+ */
+ public Builder(@NonNull CharSequence title) {
+ mTitle = requireNonNull(title);
}
- @Override
- public SafetyCenterStaticEntry[] newArray(int size) {
- return new SafetyCenterStaticEntry[size];
+ /**
+ * Creates a {@link Builder} with the values from the given {@link SafetyCenterStaticEntry}.
+ */
+ public Builder(@NonNull SafetyCenterStaticEntry safetyCenterStaticEntry) {
+ mTitle = safetyCenterStaticEntry.mTitle;
+ mSummary = safetyCenterStaticEntry.mSummary;
+ mPendingIntent = safetyCenterStaticEntry.mPendingIntent;
}
- };
+
+ /** Sets the title for this entry. */
+ @NonNull
+ public Builder setTitle(@NonNull CharSequence title) {
+ mTitle = requireNonNull(title);
+ return this;
+ }
+
+ /** Sets the optional summary text for this entry. */
+ @NonNull
+ public Builder setSummary(@Nullable CharSequence summary) {
+ mSummary = summary;
+ return this;
+ }
+
+ /** Sets the optional {@link PendingIntent} to execute when this entry is selected. */
+ @NonNull
+ public Builder setPendingIntent(@Nullable PendingIntent pendingIntent) {
+ mPendingIntent = pendingIntent;
+ return this;
+ }
+
+ /** Creates the {@link SafetyCenterStaticEntry} defined by this {@link Builder}. */
+ @NonNull
+ public SafetyCenterStaticEntry build() {
+ return new SafetyCenterStaticEntry(mTitle, mSummary, mPendingIntent);
+ }
+ }
}
diff --git a/framework-s/java/android/safetycenter/SafetyCenterStaticEntryGroup.java b/framework-s/java/android/safetycenter/SafetyCenterStaticEntryGroup.java
index 2fd14c4a5..d02741b2d 100644
--- a/framework-s/java/android/safetycenter/SafetyCenterStaticEntryGroup.java
+++ b/framework-s/java/android/safetycenter/SafetyCenterStaticEntryGroup.java
@@ -18,6 +18,7 @@ package android.safetycenter;
import static android.os.Build.VERSION_CODES.TIRAMISU;
+import static java.util.Collections.unmodifiableList;
import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
@@ -34,6 +35,7 @@ import java.util.Objects;
/**
* A group of related {@link SafetyCenterStaticEntry} objects in the Safety Center.
+ *
* @hide
*/
@SystemApi
@@ -41,6 +43,23 @@ import java.util.Objects;
public final class SafetyCenterStaticEntryGroup implements Parcelable {
@NonNull
+ public static final Creator<SafetyCenterStaticEntryGroup> CREATOR =
+ new Creator<SafetyCenterStaticEntryGroup>() {
+ @Override
+ public SafetyCenterStaticEntryGroup createFromParcel(Parcel source) {
+ CharSequence title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+ List<SafetyCenterStaticEntry> staticEntries = source.createTypedArrayList(
+ SafetyCenterStaticEntry.CREATOR);
+ return new SafetyCenterStaticEntryGroup(title, staticEntries);
+ }
+
+ @Override
+ public SafetyCenterStaticEntryGroup[] newArray(int size) {
+ return new SafetyCenterStaticEntryGroup[size];
+ }
+ };
+
+ @NonNull
private final CharSequence mTitle;
@NonNull
private final List<SafetyCenterStaticEntry> mStaticEntries;
@@ -49,7 +68,7 @@ public final class SafetyCenterStaticEntryGroup implements Parcelable {
public SafetyCenterStaticEntryGroup(
@NonNull CharSequence title, @NonNull List<SafetyCenterStaticEntry> staticEntries) {
mTitle = requireNonNull(title);
- mStaticEntries = new ArrayList<>(staticEntries);
+ mStaticEntries = unmodifiableList(new ArrayList<>(requireNonNull(staticEntries)));
}
/** Returns the title that describes this entry group. */
@@ -61,13 +80,13 @@ public final class SafetyCenterStaticEntryGroup implements Parcelable {
/** Returns the entries that comprise this entry group. */
@NonNull
public List<SafetyCenterStaticEntry> getStaticEntries() {
- return new ArrayList<>(mStaticEntries);
+ return mStaticEntries;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (!(o instanceof SafetyCenterStaticEntryGroup)) return false;
SafetyCenterStaticEntryGroup that = (SafetyCenterStaticEntryGroup) o;
return TextUtils.equals(mTitle, that.mTitle)
&& Objects.equals(mStaticEntries, that.mStaticEntries);
@@ -81,8 +100,10 @@ public final class SafetyCenterStaticEntryGroup implements Parcelable {
@Override
public String toString() {
return "SafetyCenterStaticEntryGroup{"
- + "mTitle=" + mTitle
- + ", mStaticEntries=" + mStaticEntries
+ + "mTitle="
+ + mTitle
+ + ", mStaticEntries="
+ + mStaticEntries
+ '}';
}
@@ -96,20 +117,4 @@ public final class SafetyCenterStaticEntryGroup implements Parcelable {
TextUtils.writeToParcel(mTitle, dest, flags);
dest.writeTypedList(mStaticEntries);
}
-
- @NonNull
- public static final Creator<SafetyCenterStaticEntryGroup> CREATOR =
- new Creator<SafetyCenterStaticEntryGroup>() {
- @Override
- public SafetyCenterStaticEntryGroup createFromParcel(Parcel source) {
- return new SafetyCenterStaticEntryGroup(
- TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source),
- source.createTypedArrayList(SafetyCenterStaticEntry.CREATOR));
- }
-
- @Override
- public SafetyCenterStaticEntryGroup[] newArray(int size) {
- return new SafetyCenterStaticEntryGroup[size];
- }
- };
}
diff --git a/framework-s/java/android/safetycenter/SafetyCenterStatus.java b/framework-s/java/android/safetycenter/SafetyCenterStatus.java
index 341bdabed..d2d9bde4e 100644
--- a/framework-s/java/android/safetycenter/SafetyCenterStatus.java
+++ b/framework-s/java/android/safetycenter/SafetyCenterStatus.java
@@ -42,27 +42,6 @@ import java.util.Objects;
@RequiresApi(TIRAMISU)
public final class SafetyCenterStatus implements Parcelable {
- /**
- * All possible overall severity levels for the Safety Center.
- *
- * <p>The overall severity level is calculated from the severity level and statuses of all
- * issues and entries in the Safety Center.
- *
- * @see #getSeverityLevel()
- * @see Builder#setSeverityLevel(int)
- *
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = "OVERALL_SEVERITY_LEVEL_", value = {
- OVERALL_SEVERITY_LEVEL_UNKNOWN,
- OVERALL_SEVERITY_LEVEL_OK,
- OVERALL_SEVERITY_LEVEL_RECOMMENDATION,
- OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING,
- })
- public @interface OverallSeverityLevel {
- }
-
/** Indicates the overall severity level of the Safety Center is not currently known. */
public static final int OVERALL_SEVERITY_LEVEL_UNKNOWN = 1000;
@@ -78,20 +57,25 @@ public final class SafetyCenterStatus implements Parcelable {
public static final int OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING = 1300;
/**
- * All possible refresh states for the Safety Center.
+ * All possible overall severity levels for the Safety Center.
*
- * @see #getRefreshStatus()
- * @see Builder#setRefreshStatus(int)
+ * <p>The overall severity level is calculated from the severity level and statuses of all
+ * issues and entries in the Safety Center.
*
* @hide
+ * @see #getSeverityLevel()
+ * @see Builder#setSeverityLevel(int)
*/
@Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = "REFRESH_STATUS_", value = {
- REFRESH_STATUS_NONE,
- REFRESH_STATUS_DATA_FETCH_IN_PROGRESS,
- REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS,
- })
- public @interface RefreshStatus {
+ @IntDef(
+ prefix = "OVERALL_SEVERITY_LEVEL_",
+ value = {
+ OVERALL_SEVERITY_LEVEL_UNKNOWN,
+ OVERALL_SEVERITY_LEVEL_OK,
+ OVERALL_SEVERITY_LEVEL_RECOMMENDATION,
+ OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING,
+ })
+ public @interface OverallSeverityLevel {
}
/** Indicates that no refresh is ongoing. */
@@ -116,6 +100,43 @@ public final class SafetyCenterStatus implements Parcelable {
*/
public static final int REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS = 10200;
+ /**
+ * All possible refresh states for the Safety Center.
+ *
+ * @hide
+ * @see #getRefreshStatus()
+ * @see Builder#setRefreshStatus(int)
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(
+ prefix = "REFRESH_STATUS_",
+ value = {
+ REFRESH_STATUS_NONE,
+ REFRESH_STATUS_DATA_FETCH_IN_PROGRESS,
+ REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS,
+ })
+ public @interface RefreshStatus {
+ }
+
+ @NonNull
+ public static final Creator<SafetyCenterStatus> CREATOR =
+ new Creator<SafetyCenterStatus>() {
+ @Override
+ public SafetyCenterStatus createFromParcel(Parcel in) {
+ CharSequence title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ CharSequence summary = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ return new Builder(title, summary)
+ .setSeverityLevel(in.readInt())
+ .setRefreshStatus(in.readInt())
+ .build();
+ }
+
+ @Override
+ public SafetyCenterStatus[] newArray(int size) {
+ return new SafetyCenterStatus[size];
+ }
+ };
+
@NonNull
private final CharSequence mTitle;
@NonNull
@@ -163,7 +184,7 @@ public final class SafetyCenterStatus implements Parcelable {
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (!(o instanceof SafetyCenterStatus)) return false;
SafetyCenterStatus that = (SafetyCenterStatus) o;
return mSeverityLevel == that.mSeverityLevel
&& mRefreshStatus == that.mRefreshStatus
@@ -179,10 +200,14 @@ public final class SafetyCenterStatus implements Parcelable {
@Override
public String toString() {
return "SafetyCenterStatus{"
- + "mTitle=" + mTitle
- + ", mSummary=" + mSummary
- + ", mSeverityLevel=" + mSeverityLevel
- + ", mRefreshStatus=" + mRefreshStatus
+ + "mTitle="
+ + mTitle
+ + ", mSummary="
+ + mSummary
+ + ", mSeverityLevel="
+ + mSeverityLevel
+ + ", mRefreshStatus="
+ + mRefreshStatus
+ '}';
}
@@ -199,40 +224,30 @@ public final class SafetyCenterStatus implements Parcelable {
dest.writeInt(mRefreshStatus);
}
- @NonNull
- public static final Creator<SafetyCenterStatus> CREATOR = new Creator<SafetyCenterStatus>() {
- @Override
- public SafetyCenterStatus createFromParcel(Parcel in) {
- return new Builder()
- .setTitle(TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in))
- .setSummary(TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in))
- .setSeverityLevel(in.readInt())
- .setRefreshStatus(in.readInt())
- .build();
- }
-
- @Override
- public SafetyCenterStatus[] newArray(int size) {
- return new SafetyCenterStatus[size];
- }
- };
-
/** Builder class for {@link SafetyCenterStatus}. */
public static final class Builder {
+
+ @NonNull
private CharSequence mTitle;
+ @NonNull
private CharSequence mSummary;
@OverallSeverityLevel
private int mSeverityLevel = OVERALL_SEVERITY_LEVEL_UNKNOWN;
@RefreshStatus
private int mRefreshStatus = REFRESH_STATUS_NONE;
- /** Creates an empty {@link Builder} for {@link SafetyCenterStatus}*/
- public Builder() {}
-
/**
- * Creates a pre-populated {@link Builder} with the values from the given {@link
- * SafetyCenterStatus}.
+ * Creates a new {@link Builder} for a {@link SafetyCenterStatus}.
+ *
+ * @param title an overall title for the status
+ * @param summary a summary for the status
*/
+ public Builder(@NonNull CharSequence title, @NonNull CharSequence summary) {
+ mTitle = requireNonNull(title);
+ mSummary = requireNonNull(summary);
+ }
+
+ /** Creates a {@link Builder} with the values from the given {@link SafetyCenterStatus}. */
public Builder(@NonNull SafetyCenterStatus safetyCenterStatus) {
mTitle = safetyCenterStatus.mTitle;
mSummary = safetyCenterStatus.mSummary;
@@ -240,14 +255,14 @@ public final class SafetyCenterStatus implements Parcelable {
mRefreshStatus = safetyCenterStatus.mRefreshStatus;
}
- /** Sets the title for this status. Required. */
+ /** Sets the title for this status. */
@NonNull
public Builder setTitle(@NonNull CharSequence title) {
mTitle = requireNonNull(title);
return this;
}
- /** Sets the summary text for this status. Required. */
+ /** Sets the summary text for this status. */
@NonNull
public Builder setSummary(@NonNull CharSequence summary) {
mSummary = requireNonNull(summary);
diff --git a/framework-s/java/android/safetycenter/SafetyEvent.java b/framework-s/java/android/safetycenter/SafetyEvent.java
index 97bd0fcf8..91f384d18 100644
--- a/framework-s/java/android/safetycenter/SafetyEvent.java
+++ b/framework-s/java/android/safetycenter/SafetyEvent.java
@@ -39,22 +39,7 @@ import java.util.Objects;
@SystemApi
@RequiresApi(TIRAMISU)
public final class SafetyEvent implements Parcelable {
- /**
- * Types of safety events that may trigger a set of a safety source's {@link SafetySourceData}.
- *
- * @hide
- */
- @IntDef(prefix = {"SAFETY_EVENT_TYPE_"}, value = {
- SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED,
- SAFETY_EVENT_TYPE_REFRESH_REQUESTED,
- SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED,
- SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED,
- SAFETY_EVENT_TYPE_DEVICE_LOCALE_CHANGED,
- SAFETY_EVENT_TYPE_DEVICE_REBOOTED
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Type {
- }
+
/**
* Indicates that there has been a change of state for safety source, which may be independent
* of Safety Center interactions.
@@ -68,41 +53,60 @@ public final class SafetyEvent implements Parcelable {
public static final int SAFETY_EVENT_TYPE_REFRESH_REQUESTED = 200;
/**
- * Indicates that the safety source successfully completed a resolving
- * {@link SafetySourceIssue.Action}.
+ * Indicates that the safety source successfully completed a resolving {@link
+ * SafetySourceIssue.Action}.
*/
public static final int SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED = 300;
/**
- * Indicates that the safety source failed to complete a resolving
- * {@link SafetySourceIssue.Action}.
+ * Indicates that the safety source failed to complete a resolving {@link
+ * SafetySourceIssue.Action}.
*/
public static final int SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED = 400;
- /**
- * Indicates that the device's locale changed.
- */
+ /** Indicates that the device's locale changed. */
public static final int SAFETY_EVENT_TYPE_DEVICE_LOCALE_CHANGED = 500;
+ /** Indicates that the device was rebooted. */
+ public static final int SAFETY_EVENT_TYPE_DEVICE_REBOOTED = 600;
+
/**
- * Indicates that the device was rebooted.
+ * Types of safety events that may trigger a set of a safety source's {@link SafetySourceData}.
+ *
+ * @hide
*/
- public static final int SAFETY_EVENT_TYPE_DEVICE_REBOOTED = 600;
+ @IntDef(
+ prefix = {"SAFETY_EVENT_TYPE_"},
+ value = {
+ SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED,
+ SAFETY_EVENT_TYPE_REFRESH_REQUESTED,
+ SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED,
+ SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED,
+ SAFETY_EVENT_TYPE_DEVICE_LOCALE_CHANGED,
+ SAFETY_EVENT_TYPE_DEVICE_REBOOTED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Type {
+ }
@NonNull
public static final Creator<SafetyEvent> CREATOR =
new Creator<SafetyEvent>() {
- @Override
- public SafetyEvent createFromParcel(Parcel in) {
- return new SafetyEvent(in.readInt(), in.readString(),
- in.readString(), in.readString());
- }
+ @Override
+ public SafetyEvent createFromParcel(Parcel in) {
+ int type = in.readInt();
+ return new SafetyEvent.Builder(type)
+ .setRefreshBroadcastId(in.readString())
+ .setSafetySourceIssueId(in.readString())
+ .setSafetySourceIssueActionId(in.readString())
+ .build();
+ }
- @Override
- public SafetyEvent[] newArray(int size) {
- return new SafetyEvent[size];
- }
- };
+ @Override
+ public SafetyEvent[] newArray(int size) {
+ return new SafetyEvent[size];
+ }
+ };
@Type
private final int mType;
@@ -113,7 +117,8 @@ public final class SafetyEvent implements Parcelable {
@Nullable
private final String mSafetySourceIssueActionId;
- private SafetyEvent(@Type int type,
+ private SafetyEvent(
+ @Type int type,
@Nullable String refreshBroadcastId,
@Nullable String safetySourceIssueId,
@Nullable String safetySourceIssueActionId) {
@@ -130,8 +135,8 @@ public final class SafetyEvent implements Parcelable {
}
/**
- * Returns an optional id provided by Safety Center when requesting a refresh, through
- * {@link SafetyCenterManager#EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID}.
+ * Returns an optional id provided by Safety Center when requesting a refresh, through {@link
+ * SafetyCenterManager#EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID}.
*
* <p>This will only be relevant for events of type
* {@link #SAFETY_EVENT_TYPE_REFRESH_REQUESTED}.
@@ -146,9 +151,9 @@ public final class SafetyEvent implements Parcelable {
/**
* Returns the id of the {@link SafetySourceIssue} this event is associated with (if any).
*
- * <p>This will only be relevant for events of type
- * {@link #SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED} or
- * {@link #SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED}.
+ * <p>This will only be relevant for events of type {@link
+ * #SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED} or {@link
+ * #SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED}.
*
* @see #getType()
* @see SafetySourceIssue#getId()
@@ -162,9 +167,9 @@ public final class SafetyEvent implements Parcelable {
* Returns the id of the {@link SafetySourceIssue.Action} this event is associated with (if
* any).
*
- * <p>This will only be relevant for events of type
- * {@link #SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED} or
- * {@link #SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED}.
+ * <p>This will only be relevant for events of type {@link
+ * #SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED} or {@link
+ * #SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED}.
*
* @see #getType()
* @see SafetySourceIssue.Action#getId()
@@ -200,8 +205,8 @@ public final class SafetyEvent implements Parcelable {
@Override
public int hashCode() {
- return Objects.hash(mType, mRefreshBroadcastId, mSafetySourceIssueId,
- mSafetySourceIssueActionId);
+ return Objects.hash(
+ mType, mRefreshBroadcastId, mSafetySourceIssueId, mSafetySourceIssueActionId);
}
@Override
@@ -223,6 +228,7 @@ public final class SafetyEvent implements Parcelable {
/** Builder class for {@link SafetyEvent}. */
public static final class Builder {
+
@Type
private final int mType;
@Nullable
@@ -241,8 +247,8 @@ public final class SafetyEvent implements Parcelable {
* Sets an optional broadcast id provided by Safety Center when requesting a refresh,
* through {@link SafetyCenterManager#EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID}.
*
- * <p>This will only be relevant for events of type
- * {@link #SAFETY_EVENT_TYPE_REFRESH_REQUESTED}.
+ * <p>This will only be relevant for events of type {@link
+ * #SAFETY_EVENT_TYPE_REFRESH_REQUESTED}.
*
* @see #getType()
*/
@@ -255,9 +261,9 @@ public final class SafetyEvent implements Parcelable {
/**
* Sets the id of the {@link SafetySourceIssue} this event is associated with (if any).
*
- * <p>This will only be relevant for events of type
- * {@link #SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED} or
- * {@link #SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED}.
+ * <p>This will only be relevant for events of type {@link
+ * #SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED} or {@link
+ * #SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED}.
*
* @see #getType()
* @see SafetySourceIssue#getId()
@@ -272,9 +278,9 @@ public final class SafetyEvent implements Parcelable {
* Sets the id of the {@link SafetySourceIssue.Action} this event is associated with (if
* any).
*
- * <p>This will only be relevant for events of type
- * {@link #SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED} or
- * {@link #SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED}.
+ * <p>This will only be relevant for events of type {@link
+ * #SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED} or {@link
+ * #SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED}.
*
* @see #getType()
* @see SafetySourceIssue.Action#getId()
@@ -285,13 +291,11 @@ public final class SafetyEvent implements Parcelable {
return this;
}
- /**
- * Creates the {@link SafetyEvent} represented by this {@link Builder}.
- */
+ /** Creates the {@link SafetyEvent} represented by this {@link Builder}. */
@NonNull
public SafetyEvent build() {
- return new SafetyEvent(mType, mRefreshBroadcastId, mSafetySourceIssueId,
- mSafetySourceIssueActionId);
+ return new SafetyEvent(
+ mType, mRefreshBroadcastId, mSafetySourceIssueId, mSafetySourceIssueActionId);
}
}
}
diff --git a/framework-s/java/android/safetycenter/SafetySourceData.java b/framework-s/java/android/safetycenter/SafetySourceData.java
index 70c0a8186..bbec63db5 100644
--- a/framework-s/java/android/safetycenter/SafetySourceData.java
+++ b/framework-s/java/android/safetycenter/SafetySourceData.java
@@ -18,8 +18,12 @@ package android.safetycenter;
import static android.os.Build.VERSION_CODES.TIRAMISU;
+import static com.android.internal.util.Preconditions.checkArgument;
+
+import static java.util.Collections.unmodifiableList;
import static java.util.Objects.requireNonNull;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -28,8 +32,9 @@ import android.os.Parcelable;
import androidx.annotation.RequiresApi;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -43,16 +48,116 @@ import java.util.Objects;
@RequiresApi(TIRAMISU)
public final class SafetySourceData implements Parcelable {
+ /**
+ * Indicates that no opinion is currently associated with the information provided.
+ *
+ * <p>This severity level will be reflected in the UI of a {@link SafetySourceStatus} through a
+ * grey icon.
+ *
+ * <p>For a {@link SafetySourceStatus}, this severity level indicates that the safety source
+ * currently does not have sufficient information on the severity level of the {@link
+ * SafetySourceStatus}.
+ *
+ * <p>This severity level cannot be used to indicate the severity level of a {@link
+ * SafetySourceIssue}.
+ */
+ public static final int SEVERITY_LEVEL_UNSPECIFIED = 100;
+
+ /**
+ * Indicates the presence of an informational message or the absence of any safety issues.
+ *
+ * <p>This severity level will be reflected in the UI of either a {@link SafetySourceStatus} or
+ * a {@link SafetySourceIssue} through a green icon.
+ *
+ * <p>For a {@link SafetySourceStatus}, this severity level indicates either the absence of any
+ * {@link SafetySourceIssue}s or the presence of only {@link SafetySourceIssue}s with the same
+ * severity level.
+ *
+ * <p>For a {@link SafetySourceIssue}, this severity level indicates that the {@link
+ * SafetySourceIssue} represents an informational message relating to the safety source. {@link
+ * SafetySourceIssue}s of this severity level will be dismissible by the user from the UI, and
+ * will not trigger a confirmation dialog upon a user attempting to dismiss the warning.
+ */
+ public static final int SEVERITY_LEVEL_INFORMATION = 200;
+
+ /**
+ * Indicates the presence of a medium-severity safety issue which the user is encouraged to act
+ * on.
+ *
+ * <p>This severity level will be reflected in the UI of either a {@link SafetySourceStatus} or
+ * a {@link SafetySourceIssue} through a yellow icon.
+ *
+ * <p>For a {@link SafetySourceStatus}, this severity level indicates the presence of at least
+ * one medium-severity {@link SafetySourceIssue} relating to the safety source which the user is
+ * encouraged to act on, and no {@link SafetySourceIssue}s with higher severity level.
+ *
+ * <p>For a {@link SafetySourceIssue}, this severity level indicates that the {@link
+ * SafetySourceIssue} represents a medium-severity safety issue relating to the safety source
+ * which the user is encouraged to act on. {@link SafetySourceIssue}s of this severity level
+ * will be dismissible by the user from the UI, and will trigger a confirmation dialog upon a
+ * user attempting to dismiss the warning.
+ */
+ public static final int SEVERITY_LEVEL_RECOMMENDATION = 300;
+
+ /**
+ * Indicates the presence of a critical or urgent safety issue that should be addressed by the
+ * user.
+ *
+ * <p>This severity level will be reflected in the UI of either a {@link SafetySourceStatus} or
+ * a {@link SafetySourceIssue} through a red icon.
+ *
+ * <p>For a {@link SafetySourceStatus}, this severity level indicates the presence of at least
+ * one critical or urgent {@link SafetySourceIssue} relating to the safety source that should be
+ * addressed by the user.
+ *
+ * <p>For a {@link SafetySourceIssue}, this severity level indicates that the {@link
+ * SafetySourceIssue} represents a critical or urgent safety issue relating to the safety
+ * source that should be addressed by the user. {@link SafetySourceIssue}s of this severity
+ * level will be dismissible by the user from the UI, and will trigger a confirmation dialog
+ * upon a user attempting to dismiss the warning.
+ */
+ public static final int SEVERITY_LEVEL_CRITICAL_WARNING = 400;
+
+ /**
+ * All possible severity levels for a {@link SafetySourceStatus} or a {@link SafetySourceIssue}.
+ *
+ * <p>The numerical values of the levels are not used directly, rather they are used to build a
+ * continuum of levels which support relative comparison. The higher the severity level the
+ * higher the threat to the user.
+ *
+ * <p>For a {@link SafetySourceStatus}, the severity level is meant to convey the aggregated
+ * severity of the safety source, and it contributes to the overall severity level in the Safety
+ * Center. If the {@link SafetySourceData} contains {@link SafetySourceIssue}s, the severity
+ * level of the s{@link SafetySourceStatus} must match the highest severity level among the
+ * {@link SafetySourceIssue}s.
+ *
+ * <p>For a {@link SafetySourceIssue}, not all severity levels can be used. The severity level
+ * also determines how a {@link SafetySourceIssue}s is "dismissible" by the user, i.e. how the
+ * user can choose to ignore the issue and remove it from view in the Safety Center.
+ *
+ * @hide
+ */
+ @IntDef(
+ prefix = {"SEVERITY_LEVEL_"},
+ value = {
+ SEVERITY_LEVEL_UNSPECIFIED,
+ SEVERITY_LEVEL_INFORMATION,
+ SEVERITY_LEVEL_RECOMMENDATION,
+ SEVERITY_LEVEL_CRITICAL_WARNING
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SeverityLevel {
+ }
+
@NonNull
- public static final Parcelable.Creator<SafetySourceData> CREATOR =
- new Parcelable.Creator<SafetySourceData>() {
+ public static final Creator<SafetySourceData> CREATOR =
+ new Creator<SafetySourceData>() {
@Override
public SafetySourceData createFromParcel(Parcel in) {
SafetySourceStatus status = in.readTypedObject(SafetySourceStatus.CREATOR);
List<SafetySourceIssue> issues =
- in.createTypedArrayList(SafetySourceIssue.CREATOR);
+ requireNonNull(in.createTypedArrayList(SafetySourceIssue.CREATOR));
Builder builder = new Builder().setStatus(status);
- // TODO(b/224513050): Consider simplifying by adding a new API to the builder.
for (int i = 0; i < issues.size(); i++) {
builder.addIssue(issues.get(i));
}
@@ -70,10 +175,38 @@ public final class SafetySourceData implements Parcelable {
@NonNull
private final List<SafetySourceIssue> mIssues;
- private SafetySourceData(@Nullable SafetySourceStatus status,
- @NonNull List<SafetySourceIssue> issues) {
+ private SafetySourceData(
+ @Nullable SafetySourceStatus status, @NonNull List<SafetySourceIssue> issues) {
this.mStatus = status;
- this.mIssues = new ArrayList<>(issues);
+ this.mIssues = issues;
+ }
+
+ @SeverityLevel
+ static int validateSeverityLevelForSource(int value) {
+ switch (value) {
+ case SEVERITY_LEVEL_UNSPECIFIED:
+ case SEVERITY_LEVEL_INFORMATION:
+ case SEVERITY_LEVEL_RECOMMENDATION:
+ case SEVERITY_LEVEL_CRITICAL_WARNING:
+ return value;
+ default:
+ throw new IllegalArgumentException(
+ String.format("Unexpected Level for source: %s", value));
+ }
+ }
+
+ @SeverityLevel
+ static int validateSeverityLevelForIssue(int value) {
+ switch (value) {
+ case SEVERITY_LEVEL_INFORMATION:
+ case SEVERITY_LEVEL_RECOMMENDATION:
+ case SEVERITY_LEVEL_CRITICAL_WARNING:
+ return value;
+ case SEVERITY_LEVEL_UNSPECIFIED:
+ default:
+ throw new IllegalArgumentException(
+ String.format("Unexpected Level for issue: %s", value));
+ }
}
/** Returns the data for the {@link SafetySourceStatus} to be shown in UI. */
@@ -85,7 +218,7 @@ public final class SafetySourceData implements Parcelable {
/** Returns the data for the list of {@link SafetySourceIssue}s to be shown in UI. */
@NonNull
public List<SafetySourceIssue> getIssues() {
- return new ArrayList<>(mIssues);
+ return mIssues;
}
@Override
@@ -104,8 +237,7 @@ public final class SafetySourceData implements Parcelable {
if (this == o) return true;
if (!(o instanceof SafetySourceData)) return false;
SafetySourceData that = (SafetySourceData) o;
- return Objects.equals(mStatus, that.mStatus)
- && mIssues.equals(that.mIssues);
+ return Objects.equals(mStatus, that.mStatus) && mIssues.equals(that.mIssues);
}
@Override
@@ -125,8 +257,10 @@ public final class SafetySourceData implements Parcelable {
/** Builder class for {@link SafetySourceData}. */
public static final class Builder {
+
@NonNull
private final List<SafetySourceIssue> mIssues = new ArrayList<>();
+
@Nullable
private SafetySourceStatus mStatus;
@@ -145,8 +279,8 @@ public final class SafetySourceData implements Parcelable {
}
/**
- * Clears data for all the {@link SafetySourceIssue}s that were added to this
- * {@link Builder}.
+ * Clears data for all the {@link SafetySourceIssue}s that were added to this {@link
+ * Builder}.
*/
@NonNull
public Builder clearIssues() {
@@ -157,9 +291,26 @@ public final class SafetySourceData implements Parcelable {
/** Creates the {@link SafetySourceData} defined by this {@link Builder}. */
@NonNull
public SafetySourceData build() {
- // TODO(b/207329841): Validate data matches validation in S, for eg that the status
- // and severity levels of the settings and issues are compatible.
- return new SafetySourceData(mStatus, Collections.unmodifiableList(mIssues));
+ List<SafetySourceIssue> issues = unmodifiableList(new ArrayList<>(mIssues));
+ if (mStatus != null) {
+ int issuesMaxSeverityLevel = getIssuesMaxSeverityLevel(issues);
+ if (issuesMaxSeverityLevel > SafetySourceData.SEVERITY_LEVEL_INFORMATION) {
+ checkArgument(
+ issuesMaxSeverityLevel <= mStatus.getSeverityLevel(),
+ "Safety source data must not contain any issue with a severity level "
+ + "both greater than SEVERITY_LEVEL_INFORMATION and greater "
+ + "than the status severity level");
+ }
+ }
+ return new SafetySourceData(mStatus, issues);
+ }
+
+ private static int getIssuesMaxSeverityLevel(@NonNull List<SafetySourceIssue> issues) {
+ int max = Integer.MIN_VALUE;
+ for (int i = 0; i < issues.size(); i++) {
+ max = Math.max(max, issues.get(i).getSeverityLevel());
+ }
+ return max;
}
}
}
diff --git a/framework-s/java/android/safetycenter/SafetySourceErrorDetails.java b/framework-s/java/android/safetycenter/SafetySourceErrorDetails.java
index 1b42877e6..ac813c6f4 100644
--- a/framework-s/java/android/safetycenter/SafetySourceErrorDetails.java
+++ b/framework-s/java/android/safetycenter/SafetySourceErrorDetails.java
@@ -18,6 +18,8 @@ package android.safetycenter;
import static android.os.Build.VERSION_CODES.TIRAMISU;
+import static java.util.Objects.requireNonNull;
+
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Parcel;
@@ -35,11 +37,27 @@ import java.util.Objects;
@SystemApi
@RequiresApi(TIRAMISU)
public final class SafetySourceErrorDetails implements Parcelable {
+
+ @NonNull
+ public static final Creator<SafetySourceErrorDetails> CREATOR =
+ new Creator<SafetySourceErrorDetails>() {
+ @Override
+ public SafetySourceErrorDetails createFromParcel(Parcel in) {
+ SafetyEvent safetyEvent = in.readTypedObject(SafetyEvent.CREATOR);
+ return new SafetySourceErrorDetails(safetyEvent);
+ }
+
+ @Override
+ public SafetySourceErrorDetails[] newArray(int size) {
+ return new SafetySourceErrorDetails[0];
+ }
+ };
+
@NonNull
private final SafetyEvent mSafetyEvent;
public SafetySourceErrorDetails(@NonNull SafetyEvent safetyEvent) {
- mSafetyEvent = safetyEvent;
+ mSafetyEvent = requireNonNull(safetyEvent);
}
/** Returns the safety event associated with this error. */
@@ -48,11 +66,10 @@ public final class SafetySourceErrorDetails implements Parcelable {
return mSafetyEvent;
}
-
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (!(o instanceof SafetySourceErrorDetails)) return false;
SafetySourceErrorDetails that = (SafetySourceErrorDetails) o;
return mSafetyEvent.equals(that.mSafetyEvent);
}
@@ -77,21 +94,6 @@ public final class SafetySourceErrorDetails implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeParcelable(mSafetyEvent, flags);
+ dest.writeTypedObject(mSafetyEvent, flags);
}
-
- @NonNull
- public static final Creator<SafetySourceErrorDetails> CREATOR =
- new Creator<SafetySourceErrorDetails>() {
- @Override
- public SafetySourceErrorDetails createFromParcel(Parcel in) {
- return new SafetySourceErrorDetails(
- in.readParcelable(SafetyEvent.class.getClassLoader(), SafetyEvent.class));
- }
-
- @Override
- public SafetySourceErrorDetails[] newArray(int size) {
- return new SafetySourceErrorDetails[0];
- }
- };
}
diff --git a/framework-s/java/android/safetycenter/SafetySourceIssue.java b/framework-s/java/android/safetycenter/SafetySourceIssue.java
index dc7d91236..fa3cefc7f 100644
--- a/framework-s/java/android/safetycenter/SafetySourceIssue.java
+++ b/framework-s/java/android/safetycenter/SafetySourceIssue.java
@@ -20,6 +20,7 @@ import static android.os.Build.VERSION_CODES.TIRAMISU;
import static com.android.internal.util.Preconditions.checkArgument;
+import static java.util.Collections.unmodifiableList;
import static java.util.Objects.requireNonNull;
import android.annotation.IntDef;
@@ -37,7 +38,6 @@ import androidx.annotation.RequiresApi;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -56,36 +56,6 @@ import java.util.Objects;
@RequiresApi(TIRAMISU)
public final class SafetySourceIssue implements Parcelable {
- /**
- * Indicates an informational message.
- *
- * <p>This severity will be reflected in the UI through a green icon.
- *
- * <p>Issues with this severity will be dismissible by the user from the UI, and will not
- * trigger a confirmation dialog upon a user attempting to dismiss the warning.
- */
- public static final int SEVERITY_LEVEL_INFORMATION = 200;
-
- /**
- * Indicates a medium-severity issue which the user is encouraged to act on.
- *
- * <p>This severity will be reflected in the UI through a yellow icon.
- *
- * <p>Issues with this severity will be dismissible by the user from the UI, and will trigger a
- * confirmation dialog upon a user attempting to dismiss the warning.
- */
- public static final int SEVERITY_LEVEL_RECOMMENDATION = 300;
-
- /**
- * Indicates a critical or urgent safety issue that should be addressed by the user.
- *
- * <p>This severity will be reflected in the UI through a red icon.
- *
- * <p>Issues with this severity will be dismissible by the user from the UI, and will trigger a
- * confirmation dialog upon a user attempting to dismiss the warning.
- */
- public static final int SEVERITY_LEVEL_CRITICAL_WARNING = 400;
-
/** Indicates that the risk associated with the issue is related to a user's device safety. */
public static final int ISSUE_CATEGORY_DEVICE = 100;
@@ -95,29 +65,48 @@ public final class SafetySourceIssue implements Parcelable {
/** Indicates that the risk associated with the issue is related to a user's general safety. */
public static final int ISSUE_CATEGORY_GENERAL = 300;
+ /**
+ * All possible issue categories.
+ *
+ * <p>An issue's category represents a specific area of safety that the issue relates to.
+ *
+ * <p>An issue can only have one associated category. If the issue relates to multiple areas of
+ * safety, then choose the closest area or default to {@link #ISSUE_CATEGORY_GENERAL}.
+ *
+ * @hide
+ * @see Builder#setIssueCategory(int)
+ */
+ @IntDef(
+ prefix = {"ISSUE_CATEGORY_"},
+ value = {
+ ISSUE_CATEGORY_DEVICE,
+ ISSUE_CATEGORY_ACCOUNT,
+ ISSUE_CATEGORY_GENERAL,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface IssueCategory {
+ }
+
@NonNull
- public static final Parcelable.Creator<SafetySourceIssue> CREATOR =
- new Parcelable.Creator<SafetySourceIssue>() {
+ public static final Creator<SafetySourceIssue> CREATOR =
+ new Creator<SafetySourceIssue>() {
@Override
public SafetySourceIssue createFromParcel(Parcel in) {
String id = in.readString();
- CharSequence title =
- requireNonNull(TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in));
- CharSequence subtitle =
- TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
- CharSequence summary =
- requireNonNull(TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in));
+ CharSequence title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ CharSequence subtitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ CharSequence summary = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
int severityLevel = in.readInt();
int issueCategory = in.readInt();
- List<Action> actions = in.createTypedArrayList(Action.CREATOR);
- PendingIntent onDismissPendingIntent =
- PendingIntent.readPendingIntentOrNullFromParcel(in);
- String issueTypeId = requireNonNull(in.readString());
- Builder builder = new Builder(id, title, summary, severityLevel, issueTypeId)
- .setSubtitle(subtitle)
- .setIssueCategory(issueCategory)
- .setOnDismissPendingIntent(onDismissPendingIntent);
- // TODO(b/224513050): Consider simplifying by adding a new API to the builder.
+ List<Action> actions = requireNonNull(in.createTypedArrayList(Action.CREATOR));
+ PendingIntent onDismissPendingIntent = in.readTypedObject(
+ PendingIntent.CREATOR);
+ String issueTypeId = in.readString();
+ Builder builder =
+ new Builder(id, title, summary, severityLevel, issueTypeId)
+ .setSubtitle(subtitle)
+ .setIssueCategory(issueCategory)
+ .setOnDismissPendingIntent(onDismissPendingIntent);
for (int i = 0; i < actions.size(); i++) {
builder.addAction(actions.get(i));
}
@@ -138,7 +127,7 @@ public final class SafetySourceIssue implements Parcelable {
private final CharSequence mSubtitle;
@NonNull
private final CharSequence mSummary;
- @SeverityLevel
+ @SafetySourceData.SeverityLevel
private final int mSeverityLevel;
private final List<Action> mActions;
@Nullable
@@ -148,11 +137,12 @@ public final class SafetySourceIssue implements Parcelable {
@NonNull
private final String mIssueTypeId;
- private SafetySourceIssue(@NonNull String id,
+ private SafetySourceIssue(
+ @NonNull String id,
@NonNull CharSequence title,
@Nullable CharSequence subtitle,
@NonNull CharSequence summary,
- @SeverityLevel int severityLevel,
+ @SafetySourceData.SeverityLevel int severityLevel,
@IssueCategory int issueCategory,
@NonNull List<Action> actions,
@Nullable PendingIntent onDismissPendingIntent,
@@ -200,8 +190,8 @@ public final class SafetySourceIssue implements Parcelable {
return mSummary;
}
- /** Returns the {@link SeverityLevel} of the issue. */
- @SeverityLevel
+ /** Returns the {@link SafetySourceData.SeverityLevel} of the issue. */
+ @SafetySourceData.SeverityLevel
public int getSeverityLevel() {
return mSeverityLevel;
}
@@ -226,7 +216,7 @@ public final class SafetySourceIssue implements Parcelable {
*/
@NonNull
public List<Action> getActions() {
- return new ArrayList<>(mActions);
+ return mActions;
}
/**
@@ -234,7 +224,8 @@ public final class SafetySourceIssue implements Parcelable {
*
* <p>When a safety issue is dismissed in Safety Center page, the issue is removed from view in
* Safety Center page. This method returns an additional optional action specified by the safety
- * source that should be invoked on issue dismissal.
+ * source that should be invoked on issue dismissal. The action contained in the {@link
+ * PendingIntent} cannot start an activity.
*/
@Nullable
public PendingIntent getOnDismissPendingIntent() {
@@ -247,9 +238,9 @@ public final class SafetySourceIssue implements Parcelable {
* <p>The issue type should indicate the underlying basis for the issue, for e.g. a pending
* update or a disabled security feature.
*
- * <p>The difference between this id and {@link #getId()} is that the issue type id is
- * meant to be used for logging and should therefore contain no personally identifiable
- * information (PII) (for e.g. account name).
+ * <p>The difference between this id and {@link #getId()} is that the issue type id is meant to
+ * be used for logging and should therefore contain no personally identifiable information (PII)
+ * (e.g. for account name).
*
* <p>On multiple instances of providing the same issue to be represented in Safety Center,
* provide the same issue type id across all instances.
@@ -273,7 +264,7 @@ public final class SafetySourceIssue implements Parcelable {
dest.writeInt(mSeverityLevel);
dest.writeInt(mIssueCategory);
dest.writeTypedList(mActions);
- PendingIntent.writePendingIntentOrNullToParcel(mOnDismissPendingIntent, dest);
+ dest.writeTypedObject(mOnDismissPendingIntent, flags);
dest.writeString(mIssueTypeId);
}
@@ -295,8 +286,16 @@ public final class SafetySourceIssue implements Parcelable {
@Override
public int hashCode() {
- return Objects.hash(mId, mTitle, mSubtitle, mSummary, mSeverityLevel, mIssueCategory,
- mActions, mOnDismissPendingIntent, mIssueTypeId);
+ return Objects.hash(
+ mId,
+ mTitle,
+ mSubtitle,
+ mSummary,
+ mSeverityLevel,
+ mIssueCategory,
+ mActions,
+ mOnDismissPendingIntent,
+ mIssueTypeId);
}
@Override
@@ -323,50 +322,15 @@ public final class SafetySourceIssue implements Parcelable {
+ '}';
}
- /**
- * All possible severity levels for the safety source issue.
- *
- * <p>The severity level is meant to convey the severity of the individual issue.
- *
- * <p>The higher the severity level, the worse the safety level of the source and the higher
- * the threat to the user.
- *
- * <p>The numerical values of the levels are not used directly, rather they are used to build
- * a continuum of levels which support relative comparison.
- *
- * <p>The severity also determines how the issue is "dismissible" by the user, i.e. how
- * the user can choose to ignore the issue and remove it from view in the Safety Center.
- *
- * @hide
- */
- @IntDef(prefix = {"SEVERITY_LEVEL_"}, value = {
- SEVERITY_LEVEL_INFORMATION,
- SEVERITY_LEVEL_RECOMMENDATION,
- SEVERITY_LEVEL_CRITICAL_WARNING
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface SeverityLevel {
- }
-
- /**
- * All possible issue categories.
- *
- * <p>An issue's category represents a specific area of safety that the issue relates to.
- *
- * <p>An issue can only have one associated category. If the issue relates to multiple areas of
- * safety, then choose the closest area or default to {@link #ISSUE_CATEGORY_GENERAL}.
- *
- * @hide
- * @see Builder#setIssueCategory(int)
- */
- @IntDef(prefix = {"ISSUE_CATEGORY_"}, value = {
- ISSUE_CATEGORY_DEVICE,
- ISSUE_CATEGORY_ACCOUNT,
- ISSUE_CATEGORY_GENERAL,
-
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface IssueCategory {
+ @IssueCategory
+ private static int validateIssueCategory(int value) {
+ switch (value) {
+ case ISSUE_CATEGORY_DEVICE:
+ case ISSUE_CATEGORY_ACCOUNT:
+ case ISSUE_CATEGORY_GENERAL:
+ return value;
+ }
+ throw new IllegalArgumentException(String.format("Unexpected IssueCategory: %s", value));
}
/**
@@ -375,7 +339,7 @@ public final class SafetySourceIssue implements Parcelable {
*
* <p>The purpose of the action is to allow the user to address the safety issue, either by
* performing a fix suggested in the issue, or by navigating the user to the source of the issue
- * where they can be exposed to details about the issue and further suggestions to resolve it.
+ * where they can be exposed to detail about the issue and further suggestions to resolve it.
*
* <p>The user will be allowed to invoke the action from the UI by clicking on a UI element and
* consequently resolve the issue.
@@ -386,14 +350,14 @@ public final class SafetySourceIssue implements Parcelable {
public static final class Action implements Parcelable {
@NonNull
- public static final Parcelable.Creator<Action> CREATOR =
- new Parcelable.Creator<Action>() {
+ public static final Creator<Action> CREATOR =
+ new Creator<Action>() {
@Override
public Action createFromParcel(Parcel in) {
- return new Builder(
- in.readString(),
- TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in),
- PendingIntent.readPendingIntentOrNullFromParcel(in))
+ String id = in.readString();
+ CharSequence label = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ PendingIntent pendingIntent = in.readTypedObject(PendingIntent.CREATOR);
+ return new Builder(id, label, pendingIntent)
.setWillResolve(in.readBoolean())
.setSuccessMessage(
TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in))
@@ -417,7 +381,7 @@ public final class SafetySourceIssue implements Parcelable {
private final CharSequence mSuccessMessage;
private Action(
- String id,
+ @NonNull String id,
@NonNull CharSequence label,
@NonNull PendingIntent pendingIntent,
boolean willResolve,
@@ -450,8 +414,8 @@ public final class SafetySourceIssue implements Parcelable {
/**
* Returns a {@link PendingIntent} to be fired when the action is clicked on.
*
- * <p>The {@link PendingIntent} should perform the action referred to by
- * {@link #getLabel()}.
+ * <p>The {@link PendingIntent} should perform the action referred to by {@link
+ * #getLabel()}.
*/
@NonNull
public PendingIntent getPendingIntent() {
@@ -459,9 +423,9 @@ public final class SafetySourceIssue implements Parcelable {
}
/**
- * Returns whether invoking this action will fix or address the issue sufficiently for it
- * to be considered resolved i.e. the issue will no longer need to be conveyed to the user
- * in the UI.
+ * Returns whether invoking this action will fix or address the issue sufficiently for it to
+ * be considered resolved i.e. the issue will no longer need to be conveyed to the user in
+ * the UI.
*/
public boolean willResolve() {
return mWillResolve;
@@ -485,7 +449,7 @@ public final class SafetySourceIssue implements Parcelable {
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(mId);
TextUtils.writeToParcel(mLabel, dest, flags);
- mPendingIntent.writeToParcel(dest, flags);
+ dest.writeTypedObject(mPendingIntent, flags);
dest.writeBoolean(mWillResolve);
TextUtils.writeToParcel(mSuccessMessage, dest, flags);
}
@@ -510,16 +474,22 @@ public final class SafetySourceIssue implements Parcelable {
@Override
public String toString() {
return "Action{"
- + "mId=" + mId
- + ", mLabel=" + mLabel
- + ", mPendingIntent=" + mPendingIntent
- + ", mWillResolve=" + mWillResolve
- + ", mSuccessMessage=" + mSuccessMessage
+ + "mId="
+ + mId
+ + ", mLabel="
+ + mLabel
+ + ", mPendingIntent="
+ + mPendingIntent
+ + ", mWillResolve="
+ + mWillResolve
+ + ", mSuccessMessage="
+ + mSuccessMessage
+ '}';
}
/** Builder class for {@link Action}. */
public static final class Builder {
+
@NonNull
private final String mId;
@NonNull
@@ -532,8 +502,7 @@ public final class SafetySourceIssue implements Parcelable {
/** Creates a {@link Builder} for an {@link Action}. */
public Builder(
- @NonNull String id,
- @NonNull CharSequence label,
+ @NonNull String id, @NonNull CharSequence label,
@NonNull PendingIntent pendingIntent) {
mId = requireNonNull(id);
mLabel = requireNonNull(label);
@@ -541,7 +510,7 @@ public final class SafetySourceIssue implements Parcelable {
}
/**
- * Sets whether the action will resolve the safety issue. Defaults to false.
+ * Sets whether the action will resolve the safety issue. Defaults to {@code false}.
*
* @see #willResolve()
*/
@@ -572,36 +541,37 @@ public final class SafetySourceIssue implements Parcelable {
/** Builder class for {@link SafetySourceIssue}. */
public static final class Builder {
+
@NonNull
private final String mId;
@NonNull
private final CharSequence mTitle;
- @Nullable
- private CharSequence mSubtitle;
@NonNull
private final CharSequence mSummary;
- @SeverityLevel
+ @SafetySourceData.SeverityLevel
private final int mSeverityLevel;
+ @NonNull
+ private final String mIssueTypeId;
+ private final List<Action> mActions = new ArrayList<>();
+
+ @Nullable
+ private CharSequence mSubtitle;
@IssueCategory
private int mIssueCategory = ISSUE_CATEGORY_GENERAL;
@Nullable
private PendingIntent mOnDismissPendingIntent;
- @NonNull
- private final List<Action> mActions = new ArrayList<>();
- @NonNull
- private final String mIssueTypeId;
/** Creates a {@link Builder} for a {@link SafetySourceIssue}. */
public Builder(
@NonNull String id,
@NonNull CharSequence title,
@NonNull CharSequence summary,
- @SeverityLevel int severityLevel,
+ @SafetySourceData.SeverityLevel int severityLevel,
@NonNull String issueTypeId) {
- this.mId = id;
+ this.mId = requireNonNull(id);
this.mTitle = requireNonNull(title);
this.mSummary = requireNonNull(summary);
- this.mSeverityLevel = severityLevel;
+ this.mSeverityLevel = SafetySourceData.validateSeverityLevelForIssue(severityLevel);
this.mIssueTypeId = requireNonNull(issueTypeId);
}
@@ -619,7 +589,7 @@ public final class SafetySourceIssue implements Parcelable {
*/
@NonNull
public Builder setIssueCategory(@IssueCategory int issueCategory) {
- mIssueCategory = issueCategory;
+ mIssueCategory = validateIssueCategory(issueCategory);
return this;
}
@@ -638,17 +608,20 @@ public final class SafetySourceIssue implements Parcelable {
}
/**
- * Sets an optional {@link PendingIntent} to be invoked when an issue is dismissed from
- * the UI.
+ * Sets an optional {@link PendingIntent} to be invoked when an issue is dismissed from the
+ * UI.
*
- * In particular, if the source would like to be notified of issue dismissals in Safety
+ * <p>In particular, if the source would like to be notified of issue dismissals in Safety
* Center in order to be able to dismiss or ignore issues at the source, then set this
- * field.
+ * field. The action contained in the {@link PendingIntent} must not start an activity.
*
* @see #getOnDismissPendingIntent()
*/
@NonNull
public Builder setOnDismissPendingIntent(@Nullable PendingIntent onDismissPendingIntent) {
+ checkArgument(
+ onDismissPendingIntent == null || !onDismissPendingIntent.isActivity(),
+ "Safety source issue on dismiss pending intent must not start an activity");
mOnDismissPendingIntent = onDismissPendingIntent;
return this;
}
@@ -656,12 +629,22 @@ public final class SafetySourceIssue implements Parcelable {
/** Creates the {@link SafetySourceIssue} defined by this {@link Builder}. */
@NonNull
public SafetySourceIssue build() {
- checkArgument(!mActions.isEmpty(),
+ List<SafetySourceIssue.Action> actions = unmodifiableList(
+ new ArrayList<>(mActions));
+ checkArgument(!actions.isEmpty(),
"Safety source issue must contain at least 1 action");
- checkArgument(mActions.size() <= 2,
+ checkArgument(
+ actions.size() <= 2,
"Safety source issue must not contain more than 2 actions");
- return new SafetySourceIssue(mId, mTitle, mSubtitle, mSummary, mSeverityLevel,
- mIssueCategory, Collections.unmodifiableList(mActions), mOnDismissPendingIntent,
+ return new SafetySourceIssue(
+ mId,
+ mTitle,
+ mSubtitle,
+ mSummary,
+ mSeverityLevel,
+ mIssueCategory,
+ actions,
+ mOnDismissPendingIntent,
mIssueTypeId);
}
}
diff --git a/framework-s/java/android/safetycenter/SafetySourceStatus.java b/framework-s/java/android/safetycenter/SafetySourceStatus.java
index 9868064ff..c39b54220 100644
--- a/framework-s/java/android/safetycenter/SafetySourceStatus.java
+++ b/framework-s/java/android/safetycenter/SafetySourceStatus.java
@@ -18,6 +18,8 @@ package android.safetycenter;
import static android.os.Build.VERSION_CODES.TIRAMISU;
+import static com.android.internal.util.Preconditions.checkArgument;
+
import static java.util.Objects.requireNonNull;
import android.annotation.IntDef;
@@ -36,8 +38,8 @@ import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
- * Data for a safety source status in the Safety Center page, which conveys the overall state of
- * the safety source and allows a user to navigate to the source.
+ * Data for a safety source status in the Safety Center page, which conveys the overall state of the
+ * safety source and allows a user to navigate to the source.
*
* @hide
*/
@@ -45,46 +47,16 @@ import java.util.Objects;
@RequiresApi(TIRAMISU)
public final class SafetySourceStatus implements Parcelable {
- /**
- * Indicates that no status is currently associated with the information. This may be due to the
- * source not having sufficient information or opinion on the status level.
- *
- * <p>This status will be reflected in the UI through a grey icon.
- */
- public static final int STATUS_LEVEL_NONE = 100;
-
- /**
- * Indicates that no issues were detected.
- *
- * <p>This status will be reflected in the UI through a green icon.
- */
- public static final int STATUS_LEVEL_OK = 200;
-
- /**
- * Indicates the presence of a medium-level issue which the user is encouraged to act on.
- *
- * <p>This status will be reflected in the UI through a yellow icon.
- */
- public static final int STATUS_LEVEL_RECOMMENDATION = 300;
-
- /**
- * Indicates the presence of a critical or urgent safety issue that should be addressed by the
- * user.
- *
- * <p>This status will be reflected in the UI through a red icon.
- */
- public static final int STATUS_LEVEL_CRITICAL_WARNING = 400;
-
@NonNull
- public static final Parcelable.Creator<SafetySourceStatus> CREATOR =
- new Parcelable.Creator<SafetySourceStatus>() {
+ public static final Creator<SafetySourceStatus> CREATOR =
+ new Creator<SafetySourceStatus>() {
@Override
public SafetySourceStatus createFromParcel(Parcel in) {
- return new Builder(
- TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in),
- TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in),
- in.readInt(),
- PendingIntent.readPendingIntentOrNullFromParcel(in))
+ CharSequence title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ CharSequence summary = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ int severityLevel = in.readInt();
+ return new Builder(title, summary, severityLevel)
+ .setPendingIntent(in.readTypedObject(PendingIntent.CREATOR))
.setIconAction(in.readTypedObject(IconAction.CREATOR))
.setEnabled(in.readBoolean())
.build();
@@ -100,20 +72,24 @@ public final class SafetySourceStatus implements Parcelable {
private final CharSequence mTitle;
@NonNull
private final CharSequence mSummary;
- @StatusLevel
- private final int mStatusLevel;
- @NonNull
+ @SafetySourceData.SeverityLevel
+ private final int mSeverityLevel;
+ @Nullable
private final PendingIntent mPendingIntent;
@Nullable
private final IconAction mIconAction;
private final boolean mEnabled;
- private SafetySourceStatus(@NonNull CharSequence title, @NonNull CharSequence summary,
- @StatusLevel int statusLevel, @NonNull PendingIntent pendingIntent,
- @Nullable IconAction iconAction, boolean enabled) {
+ private SafetySourceStatus(
+ @NonNull CharSequence title,
+ @NonNull CharSequence summary,
+ @SafetySourceData.SeverityLevel int severityLevel,
+ @Nullable PendingIntent pendingIntent,
+ @Nullable IconAction iconAction,
+ boolean enabled) {
this.mTitle = title;
this.mSummary = summary;
- this.mStatusLevel = statusLevel;
+ this.mSeverityLevel = severityLevel;
this.mPendingIntent = pendingIntent;
this.mIconAction = iconAction;
this.mEnabled = enabled;
@@ -131,17 +107,23 @@ public final class SafetySourceStatus implements Parcelable {
return mSummary;
}
- /** Returns the {@link StatusLevel} of the status. */
- @StatusLevel
- public int getStatusLevel() {
- return mStatusLevel;
+ /** Returns the {@link SafetySourceData.SeverityLevel} of the status. */
+ @SafetySourceData.SeverityLevel
+ public int getSeverityLevel() {
+ return mSeverityLevel;
}
/**
- * Returns the {@link PendingIntent} that will be invoked when the safety source status UI is
- * clicked on.
+ * Returns an optional {@link PendingIntent} that will start an activity when the safety source
+ * status UI is clicked on.
+ *
+ * <p>The action contained in the {@link PendingIntent} must start an activity.
+ *
+ * <p>If {@code null} the intent action defined in the Safety Center configuration will be
+ * invoked when the safety source status UI is clicked on. If the intent action is undefined or
+ * disabled the source is considered as disabled.
*/
- @NonNull
+ @Nullable
public PendingIntent getPendingIntent() {
return mPendingIntent;
}
@@ -160,10 +142,10 @@ public final class SafetySourceStatus implements Parcelable {
/**
* Returns whether the safety source status is enabled.
*
- * <p>A safety source status should be disabled if it is currently unavailable on the device.
+ * <p>A safety source status should be disabled if it is currently unavailable on the device
*
- * <p>If disabled, the status will show as grayed out in the UI, and interactions with it may
- * be limited.
+ * <p>If disabled, the status will show as grayed out in the UI, and interactions with it may be
+ * limited.
*/
public boolean isEnabled() {
return mEnabled;
@@ -178,8 +160,8 @@ public final class SafetySourceStatus implements Parcelable {
public void writeToParcel(@NonNull Parcel dest, int flags) {
TextUtils.writeToParcel(mTitle, dest, flags);
TextUtils.writeToParcel(mSummary, dest, flags);
- dest.writeInt(mStatusLevel);
- mPendingIntent.writeToParcel(dest, flags);
+ dest.writeInt(mSeverityLevel);
+ dest.writeTypedObject(mPendingIntent, flags);
dest.writeTypedObject(mIconAction, flags);
dest.writeBoolean(mEnabled);
}
@@ -189,17 +171,17 @@ public final class SafetySourceStatus implements Parcelable {
if (this == o) return true;
if (!(o instanceof SafetySourceStatus)) return false;
SafetySourceStatus that = (SafetySourceStatus) o;
- return mStatusLevel == that.mStatusLevel
+ return mSeverityLevel == that.mSeverityLevel
&& mEnabled == that.mEnabled
&& TextUtils.equals(mTitle, that.mTitle)
&& TextUtils.equals(mSummary, that.mSummary)
- && mPendingIntent.equals(that.mPendingIntent)
+ && Objects.equals(mPendingIntent, that.mPendingIntent)
&& Objects.equals(mIconAction, that.mIconAction);
}
@Override
public int hashCode() {
- return Objects.hash(mTitle, mSummary, mStatusLevel, mPendingIntent, mIconAction,
+ return Objects.hash(mTitle, mSummary, mSeverityLevel, mPendingIntent, mIconAction,
mEnabled);
}
@@ -210,8 +192,8 @@ public final class SafetySourceStatus implements Parcelable {
+ mTitle
+ ", mSummary="
+ mSummary
- + ", mStatusLevel="
- + mStatusLevel
+ + ", mSeverityLevel="
+ + mSeverityLevel
+ ", mPendingIntent="
+ mPendingIntent
+ ", mIconAction="
@@ -238,13 +220,12 @@ public final class SafetySourceStatus implements Parcelable {
public static final class IconAction implements Parcelable {
@NonNull
- public static final Parcelable.Creator<IconAction> CREATOR =
- new Parcelable.Creator<IconAction>() {
+ public static final Creator<IconAction> CREATOR =
+ new Creator<IconAction>() {
@Override
public IconAction createFromParcel(Parcel in) {
int iconType = in.readInt();
- PendingIntent pendingIntent =
- requireNonNull(PendingIntent.readPendingIntentOrNullFromParcel(in));
+ PendingIntent pendingIntent = in.readTypedObject(PendingIntent.CREATOR);
return new IconAction(iconType, pendingIntent);
}
@@ -254,14 +235,35 @@ public final class SafetySourceStatus implements Parcelable {
}
};
+ /** Indicates a gear (cog) icon. */
+ public static final int ICON_TYPE_GEAR = 100;
+
+ /** Indicates an information icon. */
+ public static final int ICON_TYPE_INFO = 200;
+
+ /**
+ * All possible icons which can be displayed in an {@link IconAction}.
+ *
+ * @hide
+ */
+ @IntDef(
+ prefix = {"ICON_TYPE_"},
+ value = {
+ ICON_TYPE_GEAR,
+ ICON_TYPE_INFO,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface IconType {
+ }
+
@IconType
private final int mIconType;
@NonNull
private final PendingIntent mPendingIntent;
public IconAction(@IconType int iconType, @NonNull PendingIntent pendingIntent) {
- this.mIconType = iconType;
- this.mPendingIntent = pendingIntent;
+ this.mIconType = validateIconType(iconType);
+ this.mPendingIntent = requireNonNull(pendingIntent);
}
/**
@@ -274,7 +276,10 @@ public final class SafetySourceStatus implements Parcelable {
return mIconType;
}
- /** Returns a {@link PendingIntent} to be invoked when the icon action is clicked on. */
+ /**
+ * Returns a {@link PendingIntent} that will start an activity when the icon action is
+ * clicked on.
+ */
@NonNull
public PendingIntent getPendingIntent() {
return mPendingIntent;
@@ -288,7 +293,7 @@ public final class SafetySourceStatus implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mIconType);
- mPendingIntent.writeToParcel(dest, flags);
+ dest.writeTypedObject(mPendingIntent, flags);
}
@Override
@@ -314,73 +319,57 @@ public final class SafetySourceStatus implements Parcelable {
+ '}';
}
- /** Indicates a gear (cog) icon. */
- public static final int ICON_TYPE_GEAR = 100;
-
- /** Indicates an information icon. */
- public static final int ICON_TYPE_INFO = 200;
-
- /**
- * All possible icons which can be displayed in an {@link IconAction}.
- *
- * @hide
- */
- @IntDef(prefix = {"ICON_TYPE_"}, value = {
- ICON_TYPE_GEAR,
- ICON_TYPE_INFO,
-
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface IconType {
+ @IconType
+ private static int validateIconType(int value) {
+ switch (value) {
+ case ICON_TYPE_GEAR:
+ case ICON_TYPE_INFO:
+ return value;
+ }
+ throw new IllegalArgumentException(String.format("Unexpected IconType: %s", value));
}
}
- /**
- * All possible status levels for the safety source status.
- *
- * <p>The status level is meant to convey the overall state of the safety source and contributes
- * to the top-level safety status of the user. Choose the status level to represent the most
- * severe of all the safety source's issues.
- *
- * <p>The numerical values of the levels are not used directly, rather they are used to build
- * a continuum of levels which support relative comparison.
- *
- * <p>The higher the status level, the worse the safety level of the source and the higher
- * the threat to the user.
- *
- * @hide
- */
- @IntDef(prefix = {"STATUS_LEVEL_"}, value = {
- STATUS_LEVEL_NONE,
- STATUS_LEVEL_OK,
- STATUS_LEVEL_RECOMMENDATION,
- STATUS_LEVEL_CRITICAL_WARNING
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface StatusLevel {
- }
-
/** Builder class for {@link SafetySourceStatus}. */
public static final class Builder {
+
@NonNull
private final CharSequence mTitle;
@NonNull
private final CharSequence mSummary;
- @StatusLevel
- private final int mStatusLevel;
- @NonNull
- private final PendingIntent mPendingIntent;
+ @SafetySourceData.SeverityLevel
+ private final int mSeverityLevel;
+
+ @Nullable
+ private PendingIntent mPendingIntent;
@Nullable
private IconAction mIconAction;
private boolean mEnabled = true;
/** Creates a {@link Builder} for a {@link SafetySourceStatus}. */
- public Builder(@NonNull CharSequence title, @NonNull CharSequence summary,
- @StatusLevel int statusLevel, @NonNull PendingIntent pendingIntent) {
+ public Builder(
+ @NonNull CharSequence title,
+ @NonNull CharSequence summary,
+ @SafetySourceData.SeverityLevel int severityLevel) {
this.mTitle = requireNonNull(title);
this.mSummary = requireNonNull(summary);
- this.mStatusLevel = statusLevel;
- this.mPendingIntent = requireNonNull(pendingIntent);
+ this.mSeverityLevel = SafetySourceData.validateSeverityLevelForSource(severityLevel);
+ }
+
+ /**
+ * Sets an optional {@link PendingIntent} for the safety source status.
+ *
+ * <p>The action contained in the {@link PendingIntent} must start an activity.
+ *
+ * @see #getPendingIntent()
+ */
+ @NonNull
+ public Builder setPendingIntent(@Nullable PendingIntent pendingIntent) {
+ checkArgument(
+ pendingIntent == null || pendingIntent.isActivity(),
+ "Safety source status pending intent must start an activity");
+ this.mPendingIntent = pendingIntent;
+ return this;
}
/**
@@ -397,12 +386,17 @@ public final class SafetySourceStatus implements Parcelable {
/**
* Sets whether the safety source status is enabled.
*
- * <p>By default, the safety source status will be enabled.
+ * <p>By default, the safety source status will be enabled. If disabled, the status severity
+ * level must be set to {@link SafetySourceData#SEVERITY_LEVEL_UNSPECIFIED}.
*
* @see #isEnabled()
*/
@NonNull
public Builder setEnabled(boolean enabled) {
+ checkArgument(
+ enabled || mSeverityLevel == SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED,
+ "Safety source status must have a severity level of "
+ + "SEVERITY_LEVEL_UNSPECIFIED when disabled");
this.mEnabled = enabled;
return this;
}
@@ -410,8 +404,8 @@ public final class SafetySourceStatus implements Parcelable {
/** Creates the {@link SafetySourceStatus} defined by this {@link Builder}. */
@NonNull
public SafetySourceStatus build() {
- return new SafetySourceStatus(mTitle, mSummary, mStatusLevel, mPendingIntent,
- mIconAction, mEnabled);
+ return new SafetySourceStatus(
+ mTitle, mSummary, mSeverityLevel, mPendingIntent, mIconAction, mEnabled);
}
}
}
diff --git a/framework-s/java/android/safetycenter/config/BuilderUtils.java b/framework-s/java/android/safetycenter/config/BuilderUtils.java
index a01eb65c5..757e45f37 100644
--- a/framework-s/java/android/safetycenter/config/BuilderUtils.java
+++ b/framework-s/java/android/safetycenter/config/BuilderUtils.java
@@ -16,19 +16,29 @@
package android.safetycenter.config;
+import static android.os.Build.VERSION_CODES.TIRAMISU;
+
import android.annotation.AnyRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.res.Resources;
+import androidx.annotation.RequiresApi;
+
import java.util.Objects;
+@RequiresApi(TIRAMISU)
final class BuilderUtils {
+
private BuilderUtils() {
}
- private static void validateAttribute(@Nullable Object attribute, @NonNull String name,
- boolean required, boolean prohibited, @Nullable Object defaultValue) {
+ private static void validateAttribute(
+ @Nullable Object attribute,
+ @NonNull String name,
+ boolean required,
+ boolean prohibited,
+ @Nullable Object defaultValue) {
if (attribute == null && required) {
throw new IllegalStateException(String.format("Required attribute %s missing", name));
}
@@ -39,15 +49,17 @@ final class BuilderUtils {
}
}
- static void validateAttribute(@Nullable Object attribute, @NonNull String name,
- boolean required, boolean prohibited) {
+ static void validateAttribute(
+ @Nullable Object attribute, @NonNull String name, boolean required,
+ boolean prohibited) {
validateAttribute(attribute, name, required, prohibited, null);
}
@AnyRes
- static int validateResId(@Nullable @AnyRes Integer value, @NonNull String name,
- boolean required, boolean prohibited) {
- validateAttribute(value, name, required, prohibited, Integer.valueOf(Resources.ID_NULL));
+ static int validateResId(
+ @Nullable @AnyRes Integer value, @NonNull String name, boolean required,
+ boolean prohibited) {
+ validateAttribute(value, name, required, prohibited, Resources.ID_NULL);
if (value == null) {
return Resources.ID_NULL;
}
@@ -57,9 +69,14 @@ final class BuilderUtils {
return value;
}
- static int validateIntDef(@Nullable Integer value, @NonNull String name,
- boolean required, boolean prohibited, int defaultValue, int... validValues) {
- validateAttribute(value, name, required, prohibited, Integer.valueOf(defaultValue));
+ static int validateIntDef(
+ @Nullable Integer value,
+ @NonNull String name,
+ boolean required,
+ boolean prohibited,
+ int defaultValue,
+ int... validValues) {
+ validateAttribute(value, name, required, prohibited, defaultValue);
if (value == null) {
return defaultValue;
}
@@ -74,22 +91,29 @@ final class BuilderUtils {
return value;
}
- static int validateInteger(@Nullable Integer value, @NonNull String name,
- boolean required, boolean prohibited, int defaultValue) {
- validateAttribute(value, name, required, prohibited, Integer.valueOf(defaultValue));
+ static int validateInteger(
+ @Nullable Integer value,
+ @NonNull String name,
+ boolean required,
+ boolean prohibited,
+ int defaultValue) {
+ validateAttribute(value, name, required, prohibited, defaultValue);
if (value == null) {
return defaultValue;
}
return value;
}
- static boolean validateBoolean(@Nullable Boolean value, @NonNull String name,
- boolean required, boolean prohibited, boolean defaultValue) {
- validateAttribute(value, name, required, prohibited, Boolean.valueOf(defaultValue));
+ static boolean validateBoolean(
+ @Nullable Boolean value,
+ @NonNull String name,
+ boolean required,
+ boolean prohibited,
+ boolean defaultValue) {
+ validateAttribute(value, name, required, prohibited, defaultValue);
if (value == null) {
return defaultValue;
}
return value;
}
-
}
diff --git a/framework-s/java/android/safetycenter/config/ParseException.java b/framework-s/java/android/safetycenter/config/ParseException.java
index 3b01e0bb7..76ba94245 100644
--- a/framework-s/java/android/safetycenter/config/ParseException.java
+++ b/framework-s/java/android/safetycenter/config/ParseException.java
@@ -24,13 +24,14 @@ import android.annotation.SystemApi;
import androidx.annotation.RequiresApi;
/**
- * Exception thrown when there is an error parsing the Safety Center configuration
+ * Exception thrown when there is an error parsing the Safety Center configuration.
*
* @hide
*/
@SystemApi
@RequiresApi(TIRAMISU)
public final class ParseException extends Exception {
+
public ParseException(@NonNull String message) {
super(message);
}
diff --git a/framework-s/java/android/safetycenter/config/SafetyCenterConfig.java b/framework-s/java/android/safetycenter/config/SafetyCenterConfig.java
index 6f2bb8d54..99544e600 100644
--- a/framework-s/java/android/safetycenter/config/SafetyCenterConfig.java
+++ b/framework-s/java/android/safetycenter/config/SafetyCenterConfig.java
@@ -18,6 +18,7 @@ package android.safetycenter.config;
import static android.os.Build.VERSION_CODES.TIRAMISU;
+import static java.util.Collections.unmodifiableList;
import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
@@ -29,20 +30,40 @@ import android.os.Parcelable;
import androidx.annotation.RequiresApi;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
/**
- * Data class used to represent the initial configuration of the Safety Center
+ * Data class used to represent the initial configuration of the Safety Center.
*
* @hide
*/
@SystemApi
@RequiresApi(TIRAMISU)
public final class SafetyCenterConfig implements Parcelable {
+
+ @NonNull
+ public static final Creator<SafetyCenterConfig> CREATOR =
+ new Creator<SafetyCenterConfig>() {
+ @Override
+ public SafetyCenterConfig createFromParcel(Parcel in) {
+ List<SafetySourcesGroup> safetySourcesGroups =
+ requireNonNull(in.createTypedArrayList(SafetySourcesGroup.CREATOR));
+ Builder builder = new Builder();
+ for (int i = 0; i < safetySourcesGroups.size(); i++) {
+ builder.addSafetySourcesGroup(safetySourcesGroups.get(i));
+ }
+ return builder.build();
+ }
+
+ @Override
+ public SafetyCenterConfig[] newArray(int size) {
+ return new SafetyCenterConfig[size];
+ }
+ };
+
@NonNull
private final List<SafetySourcesGroup> mSafetySourcesGroups;
@@ -50,6 +71,20 @@ public final class SafetyCenterConfig implements Parcelable {
mSafetySourcesGroups = safetySourcesGroups;
}
+ /**
+ * Parses and validates the given XML resource into a {@link SafetyCenterConfig} object.
+ *
+ * <p>It throws a {@link ParseException} if the given XML resource does not comply with the
+ * safety_center_config.xsd schema.
+ *
+ * @param parser the XML resource parsing interface
+ */
+ @NonNull
+ public static SafetyCenterConfig fromXml(@NonNull XmlResourceParser parser)
+ throws ParseException {
+ return SafetyCenterConfigParser.parseXmlResource(parser);
+ }
+
/** Returns the list of {@link SafetySourcesGroup}s in the configuration. */
@NonNull
public List<SafetySourcesGroup> getSafetySourcesGroups() {
@@ -72,7 +107,8 @@ public final class SafetyCenterConfig implements Parcelable {
@Override
public String toString() {
return "SafetyCenterConfig{"
- + "mSafetySourcesGroups=" + mSafetySourcesGroups
+ + "mSafetySourcesGroups="
+ + mSafetySourcesGroups
+ '}';
}
@@ -86,30 +122,9 @@ public final class SafetyCenterConfig implements Parcelable {
dest.writeTypedList(mSafetySourcesGroups);
}
- @NonNull
- public static final Parcelable.Creator<SafetyCenterConfig> CREATOR =
- new Parcelable.Creator<SafetyCenterConfig>() {
- @Override
- public SafetyCenterConfig createFromParcel(Parcel in) {
- List<SafetySourcesGroup> safetySourcesGroups =
- in.createTypedArrayList(SafetySourcesGroup.CREATOR);
- Builder builder = new Builder();
- // TODO(b/224513050): Consider simplifying by adding a new API to the builder.
- for (int i = 0; i < safetySourcesGroups.size(); i++) {
- builder.addSafetySourcesGroup(safetySourcesGroups.get(i));
- }
- return builder.build();
- }
-
- @Override
- public SafetyCenterConfig[] newArray(int size) {
- return new SafetyCenterConfig[size];
- }
- };
-
/** Builder class for {@link SafetyCenterConfig}. */
public static final class Builder {
- @NonNull
+
private final List<SafetySourcesGroup> mSafetySourcesGroups = new ArrayList<>();
/** Creates a {@link Builder} for a {@link SafetyCenterConfig}. */
@@ -126,14 +141,16 @@ public final class SafetyCenterConfig implements Parcelable {
/** Creates the {@link SafetyCenterConfig} defined by this {@link Builder}. */
@NonNull
public SafetyCenterConfig build() {
- if (mSafetySourcesGroups.isEmpty()) {
+ List<SafetySourcesGroup> safetySourcesGroups = unmodifiableList(
+ new ArrayList<>(mSafetySourcesGroups));
+ if (safetySourcesGroups.isEmpty()) {
throw new IllegalStateException("No safety sources groups present");
}
Set<String> safetySourceIds = new HashSet<>();
Set<String> safetySourcesGroupsIds = new HashSet<>();
- int safetySourcesGroupsSize = mSafetySourcesGroups.size();
+ int safetySourcesGroupsSize = safetySourcesGroups.size();
for (int i = 0; i < safetySourcesGroupsSize; i++) {
- SafetySourcesGroup safetySourcesGroup = mSafetySourcesGroups.get(i);
+ SafetySourcesGroup safetySourcesGroup = safetySourcesGroups.get(i);
String groupId = safetySourcesGroup.getId();
if (safetySourcesGroupsIds.contains(groupId)) {
throw new IllegalStateException(
@@ -152,22 +169,7 @@ public final class SafetyCenterConfig implements Parcelable {
safetySourceIds.add(sourceId);
}
}
- return new SafetyCenterConfig(Collections.unmodifiableList(mSafetySourcesGroups));
+ return new SafetyCenterConfig(safetySourcesGroups);
}
}
-
- /**
- * Parses and validates the given XML resource into a {@link SafetyCenterConfig} object.
- *
- * <p>It throws a {@link ParseException} if the given XML resource does not comply with the
- * safety_center_config.xsd schema.
- *
- * @param parser the XML resource parsing interface
- */
- @NonNull
- public static SafetyCenterConfig fromXml(@NonNull XmlResourceParser parser)
- throws ParseException {
- return SafetyCenterConfigParser.parseXmlResource(parser);
- }
-
}
diff --git a/framework-s/java/android/safetycenter/config/SafetyCenterConfigParser.java b/framework-s/java/android/safetycenter/config/SafetyCenterConfigParser.java
index 304e17a72..45d5c9f2f 100644
--- a/framework-s/java/android/safetycenter/config/SafetyCenterConfigParser.java
+++ b/framework-s/java/android/safetycenter/config/SafetyCenterConfigParser.java
@@ -44,8 +44,6 @@ import java.io.IOException;
@RequiresApi(TIRAMISU)
final class SafetyCenterConfigParser {
- private SafetyCenterConfigParser() {
- }
private static final String TAG_SAFETY_CENTER_CONFIG = "safety-center-config";
private static final String TAG_SAFETY_SOURCES_CONFIG = "safety-sources-config";
@@ -53,12 +51,10 @@ final class SafetyCenterConfigParser {
private static final String TAG_STATIC_SAFETY_SOURCE = "static-safety-source";
private static final String TAG_DYNAMIC_SAFETY_SOURCE = "dynamic-safety-source";
private static final String TAG_ISSUE_ONLY_SAFETY_SOURCE = "issue-only-safety-source";
-
private static final String ATTR_SAFETY_SOURCES_GROUP_ID = "id";
private static final String ATTR_SAFETY_SOURCES_GROUP_TITLE = "title";
private static final String ATTR_SAFETY_SOURCES_GROUP_SUMMARY = "summary";
private static final String ATTR_SAFETY_SOURCES_GROUP_STATELESS_ICON_TYPE = "statelessIconType";
-
private static final String ATTR_SAFETY_SOURCE_ID = "id";
private static final String ATTR_SAFETY_SOURCE_PACKAGE_NAME = "packageName";
private static final String ATTR_SAFETY_SOURCE_TITLE = "title";
@@ -69,24 +65,20 @@ final class SafetyCenterConfigParser {
private static final String ATTR_SAFETY_SOURCE_INITIAL_DISPLAY_STATE = "initialDisplayState";
private static final String ATTR_SAFETY_SOURCE_MAX_SEVERITY_LEVEL = "maxSeverityLevel";
private static final String ATTR_SAFETY_SOURCE_SEARCH_TERMS = "searchTerms";
- private static final String ATTR_SAFETY_SOURCE_BROADCAST_RECEIVER_CLASS_NAME =
- "broadcastReceiverClassName";
private static final String ATTR_SAFETY_SOURCE_LOGGING_ALLOWED = "loggingAllowed";
private static final String ATTR_SAFETY_SOURCE_REFRESH_ON_PAGE_OPEN_ALLOWED =
"refreshOnPageOpenAllowed";
- private static final String ATTR_SAFETY_SOURCE_AUTOMATIC_NOTIFICATION_FROM_ISSUE_ALLOWED =
- "automaticNotificationFromIssueAllowed";
-
private static final String ENUM_STATELESS_ICON_TYPE_NONE = "none";
private static final String ENUM_STATELESS_ICON_TYPE_PRIVACY = "privacy";
-
private static final String ENUM_PROFILE_PRIMARY = "primary_profile_only";
private static final String ENUM_PROFILE_ALL = "all_profiles";
-
private static final String ENUM_INITIAL_DISPLAY_STATE_ENABLED = "enabled";
private static final String ENUM_INITIAL_DISPLAY_STATE_DISABLED = "disabled";
private static final String ENUM_INITIAL_DISPLAY_STATE_HIDDEN = "hidden";
+ private SafetyCenterConfigParser() {
+ }
+
@NonNull
static SafetyCenterConfig parseXmlResource(@NonNull XmlResourceParser parser)
throws ParseException {
@@ -131,9 +123,8 @@ final class SafetyCenterConfigParser {
try {
return builder.build();
} catch (IllegalStateException e) {
- throwElementInvalid(TAG_SAFETY_SOURCES_CONFIG, e);
+ throw elementInvalid(TAG_SAFETY_SOURCES_CONFIG, e);
}
- return null; // Unreachable
}
@NonNull
@@ -154,11 +145,11 @@ final class SafetyCenterConfigParser {
break;
case ATTR_SAFETY_SOURCES_GROUP_STATELESS_ICON_TYPE:
builder.setStatelessIconType(
- parseStatelessIconType(parser.getAttributeValue(i), name,
- parser.getAttributeName(i)));
+ parseStatelessIconType(
+ parser.getAttributeValue(i), name, parser.getAttributeName(i)));
break;
default:
- throwAttributeUnexpected(name, parser.getAttributeName(i));
+ throw attributeUnexpected(name, parser.getAttributeName(i));
}
}
parser.nextTag();
@@ -185,14 +176,13 @@ final class SafetyCenterConfigParser {
try {
return builder.build();
} catch (IllegalStateException e) {
- throwElementInvalid(name, e);
+ throw elementInvalid(name, e);
}
- return null; // Unreachable
}
@NonNull
- private static SafetySource parseSafetySource(@NonNull XmlResourceParser parser,
- @SafetySourceType int type, @NonNull String name)
+ private static SafetySource parseSafetySource(
+ @NonNull XmlResourceParser parser, @SafetySourceType int type, @NonNull String name)
throws XmlPullParserException, IOException, ParseException {
SafetySource.Builder builder = new SafetySource.Builder(type);
for (int i = 0; i < parser.getAttributeCount(); i++) {
@@ -216,40 +206,35 @@ final class SafetyCenterConfigParser {
builder.setIntentAction(parser.getAttributeValue(i));
break;
case ATTR_SAFETY_SOURCE_PROFILE:
- builder.setProfile(parseProfile(parser.getAttributeValue(i), name,
- parser.getAttributeName(i)));
+ builder.setProfile(
+ parseProfile(parser.getAttributeValue(i), name,
+ parser.getAttributeName(i)));
break;
case ATTR_SAFETY_SOURCE_INITIAL_DISPLAY_STATE:
builder.setInitialDisplayState(
- parseInitialDisplayState(parser.getAttributeValue(i), name,
- parser.getAttributeName(i)));
+ parseInitialDisplayState(
+ parser.getAttributeValue(i), name, parser.getAttributeName(i)));
break;
case ATTR_SAFETY_SOURCE_MAX_SEVERITY_LEVEL:
- builder.setMaxSeverityLevel(parseInteger(parser.getAttributeValue(i), name,
- parser.getAttributeName(i)));
+ builder.setMaxSeverityLevel(
+ parseInteger(parser.getAttributeValue(i), name,
+ parser.getAttributeName(i)));
break;
case ATTR_SAFETY_SOURCE_SEARCH_TERMS:
builder.setSearchTermsResId(parseStringReference(parser, i, name));
break;
- case ATTR_SAFETY_SOURCE_BROADCAST_RECEIVER_CLASS_NAME:
- builder.setBroadcastReceiverClassName(parser.getAttributeValue(i));
- break;
case ATTR_SAFETY_SOURCE_LOGGING_ALLOWED:
- builder.setLoggingAllowed(parseBoolean(parser.getAttributeValue(i), name,
- parser.getAttributeName(i)));
- break;
- case ATTR_SAFETY_SOURCE_REFRESH_ON_PAGE_OPEN_ALLOWED:
- builder.setRefreshOnPageOpenAllowed(
+ builder.setLoggingAllowed(
parseBoolean(parser.getAttributeValue(i), name,
parser.getAttributeName(i)));
break;
- case ATTR_SAFETY_SOURCE_AUTOMATIC_NOTIFICATION_FROM_ISSUE_ALLOWED:
- builder.setAutomaticNotificationFromIssueAllowed(
+ case ATTR_SAFETY_SOURCE_REFRESH_ON_PAGE_OPEN_ALLOWED:
+ builder.setRefreshOnPageOpenAllowed(
parseBoolean(parser.getAttributeValue(i), name,
parser.getAttributeName(i)));
break;
default:
- throwAttributeUnexpected(name, parser.getAttributeName(i));
+ throw attributeUnexpected(name, parser.getAttributeName(i));
}
}
parser.nextTag();
@@ -258,123 +243,126 @@ final class SafetyCenterConfigParser {
try {
return builder.build();
} catch (IllegalStateException e) {
- throwElementInvalid(name, e);
+ throw elementInvalid(name, e);
}
- return null; // Unreachable
}
private static void validateElementStart(@NonNull XmlResourceParser parser,
- @NonNull String name) throws XmlPullParserException, ParseException {
+ @NonNull String name)
+ throws XmlPullParserException, ParseException {
if (parser.getEventType() != START_TAG || !parser.getName().equals(name)) {
- throwElementMissing(name);
+ throw elementMissing(name);
}
}
private static void validateElementEnd(@NonNull XmlResourceParser parser, @NonNull String name)
throws XmlPullParserException, ParseException {
if (parser.getEventType() != END_TAG || !parser.getName().equals(name)) {
- throwElementNotClosed(name);
+ throw elementNotClosed(name);
}
}
- private static void validateElementHasNoAttribute(@NonNull XmlResourceParser parser,
- @NonNull String name) throws ParseException {
+ private static void validateElementHasNoAttribute(
+ @NonNull XmlResourceParser parser, @NonNull String name) throws ParseException {
if (parser.getAttributeCount() != 0) {
- throwElementInvalid(name);
+ throw elementInvalid(name);
}
}
- private static void throwElementMissing(@NonNull String name) throws ParseException {
- throw new ParseException(String.format("Element %s missing", name));
+ private static ParseException elementMissing(@NonNull String name) {
+ return new ParseException(String.format("Element %s missing", name));
}
- private static void throwElementNotClosed(@NonNull String name) throws ParseException {
- throw new ParseException(String.format("Element %s not closed", name));
+ private static ParseException elementNotClosed(@NonNull String name) {
+ return new ParseException(String.format("Element %s not closed", name));
}
- private static void throwElementInvalid(@NonNull String name) throws ParseException {
- throw new ParseException(String.format("Element %s invalid", name));
+ private static ParseException elementInvalid(@NonNull String name) {
+ return new ParseException(String.format("Element %s invalid", name));
}
- private static void throwElementInvalid(@NonNull String name, @NonNull Throwable e)
- throws ParseException {
- throw new ParseException(String.format("Element %s invalid", name), e);
+ private static ParseException elementInvalid(@NonNull String name, @NonNull Throwable e) {
+ return new ParseException(String.format("Element %s invalid", name), e);
}
- private static void throwAttributeUnexpected(@NonNull String parent, @NonNull String name)
- throws ParseException {
- throw new ParseException(String.format("Unexpected attribute %s.%s", parent, name));
+ private static ParseException attributeUnexpected(@NonNull String parent,
+ @NonNull String name) {
+ return new ParseException(String.format("Unexpected attribute %s.%s", parent, name));
}
- private static void throwAttributeInvalid(@NonNull String parent, @NonNull String name)
- throws ParseException {
- throw new ParseException(String.format("Attribute %s.%s invalid", parent, name));
+ private static ParseException attributeInvalid(@NonNull String parent, @NonNull String name) {
+ return new ParseException(String.format("Attribute %s.%s invalid", parent, name));
}
- private static int parseInteger(@NonNull String valueString, @NonNull String parent,
- @NonNull String name) throws ParseException {
+ private static int parseInteger(
+ @NonNull String valueString, @NonNull String parent, @NonNull String name)
+ throws ParseException {
try {
return Integer.parseInt(valueString);
} catch (NumberFormatException e) {
- throw new ParseException(
- String.format("Attribute %s.%s invalid", parent, name), e);
+ throw new ParseException(String.format("Attribute %s.%s invalid", parent, name), e);
}
}
- private static boolean parseBoolean(@NonNull String valueString, @NonNull String parent,
- @NonNull String name) throws ParseException {
+ private static boolean parseBoolean(
+ @NonNull String valueString, @NonNull String parent, @NonNull String name)
+ throws ParseException {
String valueLowerString = valueString.toLowerCase(ROOT);
if (valueLowerString.equals("true")) {
return true;
} else if (!valueLowerString.equals("false")) {
- throw new ParseException(
- String.format("Attribute %s.%s invalid", parent, name));
+ throw new ParseException(String.format("Attribute %s.%s invalid", parent, name));
}
return false;
}
@StringRes
- private static int parseStringReference(@NonNull XmlResourceParser parser, int index,
- @NonNull String parent) throws ParseException {
+ private static int parseStringReference(
+ @NonNull XmlResourceParser parser, int index, @NonNull String parent)
+ throws ParseException {
int id = parser.getAttributeResourceValue(index, Resources.ID_NULL);
if (id == Resources.ID_NULL) {
- throw new ParseException(String.format("Reference %s in %s.%s missing or invalid",
- parser.getAttributeValue(index), parent, parser.getAttributeName(index)));
+ throw new ParseException(
+ String.format(
+ "Reference %s in %s.%s missing or invalid",
+ parser.getAttributeValue(index), parent,
+ parser.getAttributeName(index)));
}
return id;
}
@StatelessIconType
- private static int parseStatelessIconType(@NonNull String valueString, @NonNull String parent,
- @NonNull String name) throws ParseException {
+ private static int parseStatelessIconType(
+ @NonNull String valueString, @NonNull String parent, @NonNull String name)
+ throws ParseException {
switch (valueString) {
case ENUM_STATELESS_ICON_TYPE_NONE:
return SafetySourcesGroup.STATELESS_ICON_TYPE_NONE;
case ENUM_STATELESS_ICON_TYPE_PRIVACY:
return SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY;
default:
- throwAttributeInvalid(parent, name);
+ throw attributeInvalid(parent, name);
}
- return 0; // Unreachable
}
@Profile
- private static int parseProfile(@NonNull String valueString, @NonNull String parent,
- @NonNull String name) throws ParseException {
+ private static int parseProfile(
+ @NonNull String valueString, @NonNull String parent, @NonNull String name)
+ throws ParseException {
switch (valueString) {
case ENUM_PROFILE_PRIMARY:
return SafetySource.PROFILE_PRIMARY;
case ENUM_PROFILE_ALL:
return SafetySource.PROFILE_ALL;
default:
- throwAttributeInvalid(parent, name);
+ throw attributeInvalid(parent, name);
}
- return 0; // Unreachable
}
@InitialDisplayState
- private static int parseInitialDisplayState(@NonNull String valueString, @NonNull String parent,
- @NonNull String name) throws ParseException {
+ private static int parseInitialDisplayState(
+ @NonNull String valueString, @NonNull String parent, @NonNull String name)
+ throws ParseException {
switch (valueString) {
case ENUM_INITIAL_DISPLAY_STATE_ENABLED:
return SafetySource.INITIAL_DISPLAY_STATE_ENABLED;
@@ -383,8 +371,7 @@ final class SafetyCenterConfigParser {
case ENUM_INITIAL_DISPLAY_STATE_HIDDEN:
return SafetySource.INITIAL_DISPLAY_STATE_HIDDEN;
default:
- throwAttributeInvalid(parent, name);
+ throw attributeInvalid(parent, name);
}
- return 0; // Unreachable
}
}
diff --git a/framework-s/java/android/safetycenter/config/SafetySource.java b/framework-s/java/android/safetycenter/config/SafetySource.java
index 36dfb0fa0..4fb6a618f 100644
--- a/framework-s/java/android/safetycenter/config/SafetySource.java
+++ b/framework-s/java/android/safetycenter/config/SafetySource.java
@@ -41,6 +41,7 @@ import java.util.Objects;
@SystemApi
@RequiresApi(TIRAMISU)
public final class SafetySource implements Parcelable {
+
/** Static safety source. */
public static final int SAFETY_SOURCE_TYPE_STATIC = 1;
@@ -55,11 +56,13 @@ public final class SafetySource implements Parcelable {
*
* @hide
*/
- @IntDef(prefix = {"SAFETY_SOURCE_TYPE_"}, value = {
- SAFETY_SOURCE_TYPE_STATIC,
- SAFETY_SOURCE_TYPE_DYNAMIC,
- SAFETY_SOURCE_TYPE_ISSUE_ONLY
- })
+ @IntDef(
+ prefix = {"SAFETY_SOURCE_TYPE_"},
+ value = {
+ SAFETY_SOURCE_TYPE_STATIC,
+ SAFETY_SOURCE_TYPE_DYNAMIC,
+ SAFETY_SOURCE_TYPE_ISSUE_ONLY
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface SafetySourceType {
}
@@ -84,11 +87,9 @@ public final class SafetySource implements Parcelable {
*
* @hide
*/
- @IntDef(prefix = {"PROFILE_"}, value = {
- PROFILE_NONE,
- PROFILE_PRIMARY,
- PROFILE_ALL
- })
+ @IntDef(
+ prefix = {"PROFILE_"},
+ value = {PROFILE_NONE, PROFILE_PRIMARY, PROFILE_ALL})
@Retention(RetentionPolicy.SOURCE)
public @interface Profile {
}
@@ -107,15 +108,45 @@ public final class SafetySource implements Parcelable {
*
* @hide
*/
- @IntDef(prefix = {"INITIAL_DISPLAY_STATE_"}, value = {
- INITIAL_DISPLAY_STATE_ENABLED,
- INITIAL_DISPLAY_STATE_DISABLED,
- INITIAL_DISPLAY_STATE_HIDDEN
- })
+ @IntDef(
+ prefix = {"INITIAL_DISPLAY_STATE_"},
+ value = {
+ INITIAL_DISPLAY_STATE_ENABLED,
+ INITIAL_DISPLAY_STATE_DISABLED,
+ INITIAL_DISPLAY_STATE_HIDDEN
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface InitialDisplayState {
}
+ @NonNull
+ public static final Creator<SafetySource> CREATOR =
+ new Creator<SafetySource>() {
+ @Override
+ public SafetySource createFromParcel(Parcel in) {
+ int type = in.readInt();
+ return new Builder(type)
+ .setId(in.readString())
+ .setPackageName(in.readString())
+ .setTitleResId(in.readInt())
+ .setTitleForWorkResId(in.readInt())
+ .setSummaryResId(in.readInt())
+ .setIntentAction(in.readString())
+ .setProfile(in.readInt())
+ .setInitialDisplayState(in.readInt())
+ .setMaxSeverityLevel(in.readInt())
+ .setSearchTermsResId(in.readInt())
+ .setLoggingAllowed(in.readBoolean())
+ .setRefreshOnPageOpenAllowed(in.readBoolean())
+ .build();
+ }
+
+ @Override
+ public SafetySource[] newArray(int size) {
+ return new SafetySource[size];
+ }
+ };
+
@SafetySourceType
private final int mType;
@NonNull
@@ -137,13 +168,9 @@ public final class SafetySource implements Parcelable {
private final int mMaxSeverityLevel;
@StringRes
private final int mSearchTermsResId;
- @Nullable
- private final String mBroadcastReceiverClassName;
private final boolean mLoggingAllowed;
private final boolean mRefreshOnPageOpenAllowed;
- private final boolean mAutomaticNotificationFromIssueAllowed;
- /** Returns the id of this safety source. */
private SafetySource(
@SafetySourceType int type,
@NonNull String id,
@@ -156,10 +183,8 @@ public final class SafetySource implements Parcelable {
@InitialDisplayState int initialDisplayState,
int maxSeverityLevel,
@StringRes int searchTermsResId,
- @Nullable String broadcastReceiverClassName,
boolean loggingAllowed,
- boolean refreshOnPageOpenAllowed,
- boolean automaticNotificationFromIssueAllowed) {
+ boolean refreshOnPageOpenAllowed) {
mType = type;
mId = id;
mPackageName = packageName;
@@ -171,10 +196,8 @@ public final class SafetySource implements Parcelable {
mInitialDisplayState = initialDisplayState;
mMaxSeverityLevel = maxSeverityLevel;
mSearchTermsResId = searchTermsResId;
- mBroadcastReceiverClassName = broadcastReceiverClassName;
mLoggingAllowed = loggingAllowed;
mRefreshOnPageOpenAllowed = refreshOnPageOpenAllowed;
- mAutomaticNotificationFromIssueAllowed = automaticNotificationFromIssueAllowed;
}
/** Returns the type of this safety source. */
@@ -273,8 +296,8 @@ public final class SafetySource implements Parcelable {
}
/**
- * Returns the resource id of the search terms of this safety source if set; otherwise
- * {@link Resources#ID_NULL}.
+ * Returns the resource id of the search terms of this safety source if set; otherwise {@link
+ * Resources#ID_NULL}.
*/
@StringRes
public int getSearchTermsResId() {
@@ -285,16 +308,6 @@ public final class SafetySource implements Parcelable {
return mSearchTermsResId;
}
- /** Returns the broadcast receiver class name of this safety source. */
- @Nullable
- public String getBroadcastReceiverClassName() {
- if (mType == SAFETY_SOURCE_TYPE_STATIC) {
- throw new UnsupportedOperationException(
- "getBroadcastReceiverClassName unsupported for static safety source");
- }
- return mBroadcastReceiverClassName;
- }
-
/** Returns the logging allowed property of this safety source. */
public boolean isLoggingAllowed() {
if (mType == SAFETY_SOURCE_TYPE_STATIC) {
@@ -313,15 +326,6 @@ public final class SafetySource implements Parcelable {
return mRefreshOnPageOpenAllowed;
}
- /** Returns the automatic notification from issue allowed property of this safety source. */
- public boolean isAutomaticNotificationFromIssueAllowed() {
- if (mType == SAFETY_SOURCE_TYPE_STATIC) {
- throw new UnsupportedOperationException(
- "automaticNotificationFromIssueAllowed unsupported for static safety source");
- }
- return mAutomaticNotificationFromIssueAllowed;
- }
-
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -338,40 +342,60 @@ public final class SafetySource implements Parcelable {
&& mInitialDisplayState == that.mInitialDisplayState
&& mMaxSeverityLevel == that.mMaxSeverityLevel
&& mSearchTermsResId == that.mSearchTermsResId
- && Objects.equals(mBroadcastReceiverClassName, that.mBroadcastReceiverClassName)
&& mLoggingAllowed == that.mLoggingAllowed
- && mRefreshOnPageOpenAllowed == that.mRefreshOnPageOpenAllowed
- && mAutomaticNotificationFromIssueAllowed
- == that.mAutomaticNotificationFromIssueAllowed;
+ && mRefreshOnPageOpenAllowed == that.mRefreshOnPageOpenAllowed;
}
@Override
public int hashCode() {
- return Objects.hash(mType, mId, mPackageName, mTitleResId, mTitleForWorkResId,
- mSummaryResId, mIntentAction, mProfile, mInitialDisplayState, mMaxSeverityLevel,
- mSearchTermsResId, mBroadcastReceiverClassName, mLoggingAllowed,
- mRefreshOnPageOpenAllowed, mAutomaticNotificationFromIssueAllowed);
+ return Objects.hash(
+ mType,
+ mId,
+ mPackageName,
+ mTitleResId,
+ mTitleForWorkResId,
+ mSummaryResId,
+ mIntentAction,
+ mProfile,
+ mInitialDisplayState,
+ mMaxSeverityLevel,
+ mSearchTermsResId,
+ mLoggingAllowed,
+ mRefreshOnPageOpenAllowed);
}
@Override
public String toString() {
return "SafetySource{"
- + "mType=" + mType
- + ", mId='" + mId + '\''
- + ", mPackageName='" + mPackageName + '\''
- + ", mTitleResId=" + mTitleResId
- + ", mTitleForWorkResId=" + mTitleForWorkResId
- + ", mSummaryResId=" + mSummaryResId
- + ", mIntentAction='" + mIntentAction + '\''
- + ", mProfile=" + mProfile
- + ", mInitialDisplayState=" + mInitialDisplayState
- + ", mMaxSeverityLevel=" + mMaxSeverityLevel
- + ", mSearchTermsResId=" + mSearchTermsResId
- + ", mBroadcastReceiverClassName='" + mBroadcastReceiverClassName + '\''
- + ", mLoggingAllowed=" + mLoggingAllowed
- + ", mRefreshOnPageOpenAllowed=" + mRefreshOnPageOpenAllowed
- + ", mAutomaticNotificationFromIssueAllowed="
- + mAutomaticNotificationFromIssueAllowed
+ + "mType="
+ + mType
+ + ", mId='"
+ + mId
+ + '\''
+ + ", mPackageName='"
+ + mPackageName
+ + '\''
+ + ", mTitleResId="
+ + mTitleResId
+ + ", mTitleForWorkResId="
+ + mTitleForWorkResId
+ + ", mSummaryResId="
+ + mSummaryResId
+ + ", mIntentAction='"
+ + mIntentAction
+ + '\''
+ + ", mProfile="
+ + mProfile
+ + ", mInitialDisplayState="
+ + mInitialDisplayState
+ + ", mMaxSeverityLevel="
+ + mMaxSeverityLevel
+ + ", mSearchTermsResId="
+ + mSearchTermsResId
+ + ", mLoggingAllowed="
+ + mLoggingAllowed
+ + ", mRefreshOnPageOpenAllowed="
+ + mRefreshOnPageOpenAllowed
+ '}';
}
@@ -393,43 +417,13 @@ public final class SafetySource implements Parcelable {
dest.writeInt(mInitialDisplayState);
dest.writeInt(mMaxSeverityLevel);
dest.writeInt(mSearchTermsResId);
- dest.writeString(mBroadcastReceiverClassName);
dest.writeBoolean(mLoggingAllowed);
dest.writeBoolean(mRefreshOnPageOpenAllowed);
- dest.writeBoolean(mAutomaticNotificationFromIssueAllowed);
}
- @NonNull
- public static final Parcelable.Creator<SafetySource> CREATOR =
- new Parcelable.Creator<SafetySource>() {
- @Override
- public SafetySource createFromParcel(Parcel in) {
- return new Builder(in.readInt())
- .setId(in.readString())
- .setPackageName(in.readString())
- .setTitleResId(in.readInt())
- .setTitleForWorkResId(in.readInt())
- .setSummaryResId(in.readInt())
- .setIntentAction(in.readString())
- .setProfile(in.readInt())
- .setInitialDisplayState(in.readInt())
- .setMaxSeverityLevel(in.readInt())
- .setSearchTermsResId(in.readInt())
- .setBroadcastReceiverClassName(in.readString())
- .setLoggingAllowed(in.readBoolean())
- .setRefreshOnPageOpenAllowed(in.readBoolean())
- .setAutomaticNotificationFromIssueAllowed(in.readBoolean())
- .build();
- }
-
- @Override
- public SafetySource[] newArray(int size) {
- return new SafetySource[size];
- }
- };
-
/** Builder class for {@link SafetySource}. */
public static final class Builder {
+
@SafetySourceType
private final int mType;
@Nullable
@@ -459,13 +453,9 @@ public final class SafetySource implements Parcelable {
@StringRes
private Integer mSearchTermsResId;
@Nullable
- private String mBroadcastReceiverClassName;
- @Nullable
private Boolean mLoggingAllowed;
@Nullable
private Boolean mRefreshOnPageOpenAllowed;
- @Nullable
- private Boolean mAutomaticNotificationFromIssueAllowed;
/** Creates a {@link Builder} for a {@link SafetySource}. */
public Builder(@SafetySourceType int type) {
@@ -521,14 +511,14 @@ public final class SafetySource implements Parcelable {
return this;
}
- /** Sets the initial display state of this safety source. Defaults to enabled. */
+ /** Sets the initial display state of this safety source. */
@NonNull
public Builder setInitialDisplayState(@InitialDisplayState int initialDisplayState) {
mInitialDisplayState = initialDisplayState;
return this;
}
- /** Sets the maximum severity level of this safety source. Defaults to no maximum. */
+ /** Sets the maximum severity level of this safety source. */
@NonNull
public Builder setMaxSeverityLevel(int maxSeverityLevel) {
mMaxSeverityLevel = maxSeverityLevel;
@@ -542,41 +532,20 @@ public final class SafetySource implements Parcelable {
return this;
}
- /** Sets the broadcast receiver class name of this safety source. */
- @NonNull
- public Builder setBroadcastReceiverClassName(@Nullable String broadcastReceiverClassName) {
- mBroadcastReceiverClassName = broadcastReceiverClassName;
- return this;
- }
-
- /** Sets the logging allowed property of this safety source. Defaults to {@code true}. */
+ /** Sets the logging allowed property of this safety source. */
@NonNull
public Builder setLoggingAllowed(boolean loggingAllowed) {
mLoggingAllowed = loggingAllowed;
return this;
}
- /**
- * Sets the refresh on page open allowed property of this safety source. Defaults to {@code
- * false}.
- */
+ /** Sets the refresh on page open allowed property of this safety source. */
@NonNull
public Builder setRefreshOnPageOpenAllowed(boolean refreshOnPageOpenAllowed) {
mRefreshOnPageOpenAllowed = refreshOnPageOpenAllowed;
return this;
}
- /**
- * Sets the automatic notification from issue allowed property of this safety source.
- * Defaults to {@code false}.
- */
- @NonNull
- public Builder setAutomaticNotificationFromIssueAllowed(
- boolean automaticNotificationFromIssueAllowed) {
- mAutomaticNotificationFromIssueAllowed = automaticNotificationFromIssueAllowed;
- return this;
- }
-
/** Creates the {@link SafetySource} defined by this {@link Builder}. */
@NonNull
public SafetySource build() {
@@ -589,43 +558,73 @@ public final class SafetySource implements Parcelable {
boolean isDynamic = mType == SAFETY_SOURCE_TYPE_DYNAMIC;
boolean isIssueOnly = mType == SAFETY_SOURCE_TYPE_ISSUE_ONLY;
BuilderUtils.validateAttribute(mId, "id", true, false);
- BuilderUtils.validateAttribute(mPackageName, "packageName", isDynamic || isIssueOnly,
- isStatic);
- int initialDisplayState = BuilderUtils.validateIntDef(mInitialDisplayState,
- "initialDisplayState", false, isStatic || isIssueOnly,
- INITIAL_DISPLAY_STATE_ENABLED, INITIAL_DISPLAY_STATE_ENABLED,
- INITIAL_DISPLAY_STATE_DISABLED, INITIAL_DISPLAY_STATE_HIDDEN);
+ BuilderUtils.validateAttribute(
+ mPackageName, "packageName", isDynamic || isIssueOnly, isStatic);
+ int initialDisplayState =
+ BuilderUtils.validateIntDef(
+ mInitialDisplayState,
+ "initialDisplayState",
+ false,
+ isStatic || isIssueOnly,
+ INITIAL_DISPLAY_STATE_ENABLED,
+ INITIAL_DISPLAY_STATE_ENABLED,
+ INITIAL_DISPLAY_STATE_DISABLED,
+ INITIAL_DISPLAY_STATE_HIDDEN);
boolean isEnabled = initialDisplayState == INITIAL_DISPLAY_STATE_ENABLED;
boolean isHidden = initialDisplayState == INITIAL_DISPLAY_STATE_HIDDEN;
- int titleResId = BuilderUtils.validateResId(mTitleResId, "title",
- (isDynamic && !isHidden) || isStatic, isIssueOnly || isHidden);
- int summaryResId = BuilderUtils.validateResId(mSummaryResId, "summary",
- (isDynamic && !isHidden) || isStatic, isIssueOnly || isHidden);
- BuilderUtils.validateAttribute(mIntentAction, "intentAction",
- (isDynamic && isEnabled) || isStatic, isIssueOnly || isHidden);
- int profile = BuilderUtils.validateIntDef(mProfile, "profile", true, false,
- PROFILE_NONE, PROFILE_PRIMARY, PROFILE_ALL);
- int titleForWorkResId = BuilderUtils.validateResId(mTitleForWorkResId, "titleForWork",
- ((isDynamic && !isHidden) || isStatic) && profile == PROFILE_ALL,
- isIssueOnly || isHidden || profile == PROFILE_PRIMARY);
- int maxSeverityLevel = BuilderUtils.validateInteger(mMaxSeverityLevel,
- "maxSeverityLevel", false, isStatic, Integer.MAX_VALUE);
- int searchTermsResId = BuilderUtils.validateResId(mSearchTermsResId, "searchTerms",
- false, isIssueOnly);
- BuilderUtils.validateAttribute(mBroadcastReceiverClassName,
- "broadcastReceiverClassName", false, isStatic);
- boolean loggingAllowed = BuilderUtils.validateBoolean(mLoggingAllowed, "loggingAllowed",
- false, isStatic, true);
- boolean refreshOnPageOpenAllowed = BuilderUtils.validateBoolean(
- mRefreshOnPageOpenAllowed, "refreshOnPageOpenAllowed", false, isStatic, false);
- boolean automaticNotificationFromIssueAllowed = BuilderUtils.validateBoolean(
- mAutomaticNotificationFromIssueAllowed, "automaticNotificationFromIssueAllowed",
- false, isStatic, false);
- return new SafetySource(mType, mId, mPackageName, titleResId, titleForWorkResId,
- summaryResId, mIntentAction, profile, initialDisplayState, maxSeverityLevel,
- searchTermsResId, mBroadcastReceiverClassName, loggingAllowed,
- refreshOnPageOpenAllowed, automaticNotificationFromIssueAllowed);
+ int titleResId =
+ BuilderUtils.validateResId(
+ mTitleResId, "title", (isDynamic && !isHidden) || isStatic,
+ isIssueOnly || isHidden);
+ int summaryResId =
+ BuilderUtils.validateResId(
+ mSummaryResId,
+ "summary",
+ (isDynamic && !isHidden) || isStatic,
+ isIssueOnly || isHidden);
+ BuilderUtils.validateAttribute(
+ mIntentAction,
+ "intentAction",
+ (isDynamic && isEnabled) || isStatic,
+ isIssueOnly || isHidden);
+ int profile =
+ BuilderUtils.validateIntDef(
+ mProfile, "profile", true, false, PROFILE_NONE, PROFILE_PRIMARY,
+ PROFILE_ALL);
+ int titleForWorkResId =
+ BuilderUtils.validateResId(
+ mTitleForWorkResId,
+ "titleForWork",
+ ((isDynamic && !isHidden) || isStatic) && profile == PROFILE_ALL,
+ isIssueOnly || isHidden || profile == PROFILE_PRIMARY);
+ int maxSeverityLevel =
+ BuilderUtils.validateInteger(
+ mMaxSeverityLevel, "maxSeverityLevel", false, isStatic,
+ Integer.MAX_VALUE);
+ int searchTermsResId =
+ BuilderUtils.validateResId(mSearchTermsResId, "searchTerms", false,
+ isIssueOnly);
+ boolean loggingAllowed =
+ BuilderUtils.validateBoolean(mLoggingAllowed, "loggingAllowed", false, isStatic,
+ true);
+ boolean refreshOnPageOpenAllowed =
+ BuilderUtils.validateBoolean(
+ mRefreshOnPageOpenAllowed, "refreshOnPageOpenAllowed", false, isStatic,
+ false);
+ return new SafetySource(
+ mType,
+ mId,
+ mPackageName,
+ titleResId,
+ titleForWorkResId,
+ summaryResId,
+ mIntentAction,
+ profile,
+ initialDisplayState,
+ maxSeverityLevel,
+ searchTermsResId,
+ loggingAllowed,
+ refreshOnPageOpenAllowed);
}
}
-
}
diff --git a/framework-s/java/android/safetycenter/config/SafetySourcesGroup.java b/framework-s/java/android/safetycenter/config/SafetySourcesGroup.java
index e76d9a634..886d1071b 100644
--- a/framework-s/java/android/safetycenter/config/SafetySourcesGroup.java
+++ b/framework-s/java/android/safetycenter/config/SafetySourcesGroup.java
@@ -18,6 +18,7 @@ package android.safetycenter.config;
import static android.os.Build.VERSION_CODES.TIRAMISU;
+import static java.util.Collections.unmodifiableList;
import static java.util.Objects.requireNonNull;
import android.annotation.IntDef;
@@ -34,7 +35,6 @@ import androidx.annotation.RequiresApi;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -49,19 +49,17 @@ public final class SafetySourcesGroup implements Parcelable {
/**
* Indicates that the safety sources group should be displayed as a collapsible group with an
- * icon (stateless or stateful) and an optional default summary
+ * icon (stateless or stateful) and an optional default summary.
*/
public static final int SAFETY_SOURCES_GROUP_TYPE_COLLAPSIBLE = 0;
/**
* Indicates that the safety sources group should be displayed as a rigid group with no icon and
- * no summary
+ * no summary.
*/
public static final int SAFETY_SOURCES_GROUP_TYPE_RIGID = 1;
- /**
- * Indicates that the safety sources group should not be displayed.
- */
+ /** Indicates that the safety sources group should not be displayed. */
public static final int SAFETY_SOURCES_GROUP_TYPE_HIDDEN = 2;
/**
@@ -70,11 +68,13 @@ public final class SafetySourcesGroup implements Parcelable {
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = "SAFETY_SOURCES_GROUP_TYPE_", value = {
- SAFETY_SOURCES_GROUP_TYPE_COLLAPSIBLE,
- SAFETY_SOURCES_GROUP_TYPE_RIGID,
- SAFETY_SOURCES_GROUP_TYPE_HIDDEN
- })
+ @IntDef(
+ prefix = "SAFETY_SOURCES_GROUP_TYPE_",
+ value = {
+ SAFETY_SOURCES_GROUP_TYPE_COLLAPSIBLE,
+ SAFETY_SOURCES_GROUP_TYPE_RIGID,
+ SAFETY_SOURCES_GROUP_TYPE_HIDDEN
+ })
public @interface SafetySourceGroupType {
}
@@ -96,14 +96,38 @@ public final class SafetySourcesGroup implements Parcelable {
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = "STATELESS_ICON_TYPE_", value = {
- STATELESS_ICON_TYPE_NONE,
- STATELESS_ICON_TYPE_PRIVACY
- })
+ @IntDef(
+ prefix = "STATELESS_ICON_TYPE_",
+ value = {STATELESS_ICON_TYPE_NONE, STATELESS_ICON_TYPE_PRIVACY})
public @interface StatelessIconType {
}
@NonNull
+ public static final Creator<SafetySourcesGroup> CREATOR =
+ new Creator<SafetySourcesGroup>() {
+ @Override
+ public SafetySourcesGroup createFromParcel(Parcel in) {
+ Builder builder =
+ new Builder()
+ .setId(in.readString())
+ .setTitleResId(in.readInt())
+ .setSummaryResId(in.readInt())
+ .setStatelessIconType(in.readInt());
+ List<SafetySource> safetySources =
+ requireNonNull(in.createTypedArrayList(SafetySource.CREATOR));
+ for (int i = 0; i < safetySources.size(); i++) {
+ builder.addSafetySource(safetySources.get(i));
+ }
+ return builder.build();
+ }
+
+ @Override
+ public SafetySourcesGroup[] newArray(int size) {
+ return new SafetySourcesGroup[size];
+ }
+ };
+
+ @NonNull
private final String mId;
@StringRes
private final int mTitleResId;
@@ -188,12 +212,18 @@ public final class SafetySourcesGroup implements Parcelable {
@Override
public String toString() {
- return "SafetyCenterConfig{"
- + "mId='" + mId + '\''
- + ", mTitleResId=" + mTitleResId
- + ", mSummaryResId=" + mSummaryResId
- + ", mStatelessIconType=" + mStatelessIconType
- + ", mSafetySources=" + mSafetySources
+ return "SafetySourcesGroup{"
+ + "mId='"
+ + mId
+ + '\''
+ + ", mTitleResId="
+ + mTitleResId
+ + ", mSummaryResId="
+ + mSummaryResId
+ + ", mStatelessIconType="
+ + mStatelessIconType
+ + ", mSafetySources="
+ + mSafetySources
+ '}';
}
@@ -211,33 +241,11 @@ public final class SafetySourcesGroup implements Parcelable {
dest.writeTypedList(mSafetySources);
}
- @NonNull
- public static final Parcelable.Creator<SafetySourcesGroup> CREATOR =
- new Parcelable.Creator<SafetySourcesGroup>() {
- @Override
- public SafetySourcesGroup createFromParcel(Parcel in) {
- Builder builder = new Builder()
- .setId(in.readString())
- .setTitleResId(in.readInt())
- .setSummaryResId(in.readInt())
- .setStatelessIconType(in.readInt());
- List<SafetySource> safetySources =
- in.createTypedArrayList(SafetySource.CREATOR);
- // TODO(b/224513050): Consider simplifying by adding a new API to the builder.
- for (int i = 0; i < safetySources.size(); i++) {
- builder.addSafetySource(safetySources.get(i));
- }
- return builder.build();
- }
-
- @Override
- public SafetySourcesGroup[] newArray(int size) {
- return new SafetySourcesGroup[size];
- }
- };
-
/** Builder class for {@link SafetySourcesGroup}. */
public static final class Builder {
+
+ private final List<SafetySource> mSafetySources = new ArrayList<>();
+
@Nullable
private String mId;
@Nullable
@@ -249,8 +257,6 @@ public final class SafetySourcesGroup implements Parcelable {
@Nullable
@StatelessIconType
private Integer mStatelessIconType;
- @NonNull
- private final List<SafetySource> mSafetySources = new ArrayList<>();
/** Creates a {@link Builder} for a {@link SafetySourcesGroup}. */
public Builder() {
@@ -295,13 +301,14 @@ public final class SafetySourcesGroup implements Parcelable {
@NonNull
public SafetySourcesGroup build() {
BuilderUtils.validateAttribute(mId, "id", true, false);
- if (mSafetySources.isEmpty()) {
+ List<SafetySource> safetySources = unmodifiableList(new ArrayList<>(mSafetySources));
+ if (safetySources.isEmpty()) {
throw new IllegalStateException("Safety sources group empty");
}
boolean titleRequired = false;
- int safetySourcesSize = mSafetySources.size();
+ int safetySourcesSize = safetySources.size();
for (int i = 0; i < safetySourcesSize; i++) {
- int type = mSafetySources.get(i).getType();
+ int type = safetySources.get(i).getType();
if (type != SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY) {
titleRequired = true;
break;
@@ -309,12 +316,21 @@ public final class SafetySourcesGroup implements Parcelable {
}
int titleResId = BuilderUtils.validateResId(mTitleResId, "title", titleRequired, false);
int summaryResId = BuilderUtils.validateResId(mSummaryResId, "summary", false, false);
- int statelessIconType = BuilderUtils.validateIntDef(mStatelessIconType,
- "statelessIconType", false, false, STATELESS_ICON_TYPE_NONE,
- STATELESS_ICON_TYPE_NONE, STATELESS_ICON_TYPE_PRIVACY);
- return new SafetySourcesGroup(mId, titleResId, summaryResId, statelessIconType,
- Collections.unmodifiableList(mSafetySources));
+ int statelessIconType =
+ BuilderUtils.validateIntDef(
+ mStatelessIconType,
+ "statelessIconType",
+ false,
+ false,
+ STATELESS_ICON_TYPE_NONE,
+ STATELESS_ICON_TYPE_NONE,
+ STATELESS_ICON_TYPE_PRIVACY);
+ return new SafetySourcesGroup(
+ mId,
+ titleResId,
+ summaryResId,
+ statelessIconType,
+ safetySources);
}
}
-
}
diff --git a/service/Android.bp b/service/Android.bp
index a837fff66..86e320418 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -100,9 +100,15 @@ java_sdk_library {
//"framework-permission",
"framework-permission-s.impl",
"framework-permission-s-shared",
+
+ // Soong fails to automatically add this dependency because all the
+ // *.kt sources are inside a filegroup.
+ // Exclude Kotlin sources for T.
+ //"kotlin-annotations",
],
static_libs: [
- "kotlin-stdlib",
+ // Exclude Kotlin sources for T.
+ //"kotlin-stdlib",
"modules-utils-backgroundthread",
"modules-utils-os",
"safety-center-resources-lib",
diff --git a/service/java/com/android/role/RoleShellCommand.java b/service/java/com/android/role/RoleShellCommand.java
index f4976bf16..357ce5f76 100644
--- a/service/java/com/android/role/RoleShellCommand.java
+++ b/service/java/com/android/role/RoleShellCommand.java
@@ -80,6 +80,8 @@ class RoleShellCommand extends BasicShellCommandHandler {
return runRemoveRoleHolder();
case "clear-role-holders":
return runClearRoleHolders();
+ case "set-bypassing-role-qualification":
+ return runSetBypassingRoleQualification();
default:
return handleDefaultCommands(cmd);
}
@@ -140,6 +142,12 @@ class RoleShellCommand extends BasicShellCommandHandler {
return future.waitForResult();
}
+ private int runSetBypassingRoleQualification() throws RemoteException {
+ Boolean value = Boolean.parseBoolean(getNextArgRequired());
+ mRoleManager.setBypassingRoleQualification(value);
+ return 0;
+ }
+
@Override
public void onHelp() {
PrintWriter pw = getOutPrintWriter();
@@ -150,6 +158,7 @@ class RoleShellCommand extends BasicShellCommandHandler {
pw.println(" add-role-holder [--user USER_ID] ROLE PACKAGE [FLAGS]");
pw.println(" remove-role-holder [--user USER_ID] ROLE PACKAGE [FLAGS]");
pw.println(" clear-role-holders [--user USER_ID] ROLE [FLAGS]");
+ pw.println(" set-bypassing-role-qualification true|false");
pw.println();
}
}
diff --git a/service/java/com/android/safetycenter/OWNERS b/service/java/com/android/safetycenter/OWNERS
new file mode 100644
index 000000000..72fe70201
--- /dev/null
+++ b/service/java/com/android/safetycenter/OWNERS
@@ -0,0 +1 @@
+include /SafetyCenter/OWNERS
diff --git a/service/java/com/android/safetycenter/SafetyCenterDataTracker.java b/service/java/com/android/safetycenter/SafetyCenterDataTracker.java
index 308f3b161..518047b71 100644
--- a/service/java/com/android/safetycenter/SafetyCenterDataTracker.java
+++ b/service/java/com/android/safetycenter/SafetyCenterDataTracker.java
@@ -158,12 +158,12 @@ final class SafetyCenterDataTracker {
@NonNull
static SafetyCenterData getDefaultSafetyCenterData() {
return new SafetyCenterData(
- new SafetyCenterStatus.Builder()
- .setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_UNKNOWN)
- .setTitle(getSafetyCenterStatusTitle(
- SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_UNKNOWN))
- .setSummary(getSafetyCenterStatusSummary(
+ new SafetyCenterStatus.Builder(
+ getSafetyCenterStatusTitle(
+ SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_UNKNOWN),
+ getSafetyCenterStatusSummary(
SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_UNKNOWN))
+ .setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_UNKNOWN)
.build(),
emptyList(),
emptyList(),
@@ -251,10 +251,10 @@ final class SafetyCenterDataTracker {
int safetyCenterOverallSeverityLevel = entryToSafetyCenterStatusOverallLevel(
maxSafetyCenterEntryLevel);
return new SafetyCenterData(
- new SafetyCenterStatus.Builder()
+ new SafetyCenterStatus.Builder(
+ getSafetyCenterStatusTitle(safetyCenterOverallSeverityLevel),
+ getSafetyCenterStatusSummary(safetyCenterOverallSeverityLevel))
.setSeverityLevel(safetyCenterOverallSeverityLevel)
- .setTitle(getSafetyCenterStatusTitle(safetyCenterOverallSeverityLevel))
- .setSummary(getSafetyCenterStatusSummary(safetyCenterOverallSeverityLevel))
.build(),
safetyCenterIssues,
safetyCenterEntryOrGroups,
@@ -305,21 +305,22 @@ final class SafetyCenterDataTracker {
SafetySourceIssue.Action safetySourceIssueAction = safetySourceIssueActions.get(i);
safetyCenterIssueActions.add(
- new SafetyCenterIssue.Action.Builder(safetySourceIssue.getId())
- .setLabel(safetySourceIssueAction.getLabel())
+ new SafetyCenterIssue.Action.Builder(safetySourceIssue.getId(),
+ safetySourceIssueAction.getLabel(),
+ safetySourceIssueAction.getPendingIntent())
.setSuccessMessage(safetySourceIssueAction.getSuccessMessage())
- .setPendingIntent(safetySourceIssueAction.getPendingIntent())
.build()
);
}
// TODO(b/218817233): Add missing fields like: dismissible, shouldConfirmDismissal.
- return new SafetyCenterIssue.Builder(safetySourceIssue.getId())
+ return new SafetyCenterIssue.Builder(
+ safetySourceIssue.getId(),
+ safetySourceIssue.getTitle(),
+ safetySourceIssue.getSummary())
.setSeverityLevel(
sourceToSafetyCenterIssueSeverityLevel(
safetySourceIssue.getSeverityLevel()))
- .setTitle(safetySourceIssue.getTitle())
- .setSummary(safetySourceIssue.getSummary())
.setSubtitle(safetySourceIssue.getSubtitle())
.setActions(safetyCenterIssueActions)
.build();
@@ -351,10 +352,11 @@ final class SafetyCenterDataTracker {
// TODO(b/218817233): Add missing fields like: statelessIconType.
safetyCenterEntryOrGroups.add(
new SafetyCenterEntryOrGroup(
- new SafetyCenterEntryGroup.Builder(safetySourcesGroup.getId())
- .setSeverityLevel(maxSafetyCenterEntryLevel)
- .setTitle(mSafetyCenterConfigReader.readStringResource(
+ new SafetyCenterEntryGroup.Builder(
+ safetySourcesGroup.getId(),
+ mSafetyCenterConfigReader.readStringResource(
safetySourcesGroup.getTitleResId()))
+ .setSeverityLevel(maxSafetyCenterEntryLevel)
.setSummary(mSafetyCenterConfigReader.readStringResource(
safetySourcesGroup.getSummaryResId()))
.setEntries(entries)
@@ -379,13 +381,20 @@ final class SafetyCenterDataTracker {
mSafetySourceDataForKey.get(key));
// TODO(b/218817233): Add missing fields like: iconAction, statelessIconType.
if (safetySourceStatus != null) {
- return new SafetyCenterEntry.Builder(safetySource.getId())
+ PendingIntent pendingIntent = safetySourceStatus.getPendingIntent();
+ if (pendingIntent == null) {
+ pendingIntent = toPendingIntent(safetySource.getIntentAction(),
+ safetySource.getPackageName());
+ // TODO(b/222838784): Automatically mark the source as disabled if the
+ // pending intent is null again.
+ }
+ return new SafetyCenterEntry.Builder(safetySource.getId(),
+ safetySourceStatus.getTitle())
.setSeverityLevel(sourceToSafetyCenterEntrySeverityLevel(
- safetySourceStatus.getStatusLevel()))
- .setTitle(safetySourceStatus.getTitle())
+ safetySourceStatus.getSeverityLevel()))
.setSummary(safetySourceStatus.getSummary())
.setEnabled(safetySourceStatus.isEnabled())
- .setPendingIntent(safetySourceStatus.getPendingIntent()).build();
+ .setPendingIntent(pendingIntent).build();
}
return toDefaultSafetyCenterEntry(safetySource, safetySource.getPackageName(),
SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_UNSPECIFIED);
@@ -405,19 +414,20 @@ final class SafetyCenterDataTracker {
@NonNull SafetySource safetySource,
@Nullable String packageName,
@SafetyCenterEntry.EntrySeverityLevel int entrySeverityLevel) {
- PendingIntent pendingIntent = toPendingIntent(safetySource.getIntentAction(), packageName);
-
- if (pendingIntent == null) {
- // TODO(b/218817241): We may make the PendingIntent nullable, in which case
- // we won't want to skip here.
+ if (safetySource.getType() == SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC
+ && safetySource.getInitialDisplayState()
+ == SafetySource.INITIAL_DISPLAY_STATE_HIDDEN) {
return null;
}
+ PendingIntent pendingIntent = toPendingIntent(safetySource.getIntentAction(), packageName);
+
// TODO(b/218817233): Add missing fields like: enabled.
- return new SafetyCenterEntry.Builder(safetySource.getId())
+ // TODO(b/222838784): Automatically mark the source as disabled (both dynamic and static?)
+ // if the pending intent is null.
+ return new SafetyCenterEntry.Builder(safetySource.getId(),
+ mSafetyCenterConfigReader.readStringResource(safetySource.getTitleResId()))
.setSeverityLevel(entrySeverityLevel)
- .setTitle(mSafetyCenterConfigReader.readStringResource(
- safetySource.getTitleResId()))
.setSummary(mSafetyCenterConfigReader.readStringResource(
safetySource.getSummaryResId()))
.setPendingIntent(pendingIntent).build();
@@ -439,19 +449,18 @@ final class SafetyCenterDataTracker {
PendingIntent pendingIntent = toPendingIntent(safetySource.getIntentAction(),
null);
if (pendingIntent == null) {
- // TODO(b/218817241): We may make the PendingIntent nullable, in which case we
- // won't want to skip here.
+ // TODO(b/222838784): Decide strategy for static entries when the intent is null.
continue;
}
staticEntries.add(
- new SafetyCenterStaticEntry(
+ new SafetyCenterStaticEntry.Builder(
mSafetyCenterConfigReader.readStringResource(
- safetySource.getTitleResId()),
- mSafetyCenterConfigReader.readStringResource(
- safetySource.getSummaryResId()),
- pendingIntent
- )
+ safetySource.getTitleResId()))
+ .setSummary(mSafetyCenterConfigReader.readStringResource(
+ safetySource.getSummaryResId()))
+ .setPendingIntent(pendingIntent)
+ .build()
);
}
@@ -483,6 +492,7 @@ final class SafetyCenterDataTracker {
return null;
}
}
+ // TODO(b/222838784): Validate that the intent action is available.
// TODO(b/219699223): Is it safe to create a PendingIntent as system server here?
final long identity = Binder.clearCallingIdentity();
@@ -547,37 +557,42 @@ final class SafetyCenterDataTracker {
@SafetyCenterEntry.EntrySeverityLevel
private static int sourceToSafetyCenterEntrySeverityLevel(
- @SafetySourceStatus.StatusLevel int safetySourceStatusLevel) {
- switch (safetySourceStatusLevel) {
- case SafetySourceStatus.STATUS_LEVEL_NONE:
+ @SafetySourceData.SeverityLevel int safetySourceSeverityLevel) {
+ switch (safetySourceSeverityLevel) {
+ case SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED:
return SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_UNSPECIFIED;
- case SafetySourceStatus.STATUS_LEVEL_OK:
+ case SafetySourceData.SEVERITY_LEVEL_INFORMATION:
return SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK;
- case SafetySourceStatus.STATUS_LEVEL_RECOMMENDATION:
+ case SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION:
return SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION;
- case SafetySourceStatus.STATUS_LEVEL_CRITICAL_WARNING:
+ case SafetySourceData.SEVERITY_LEVEL_CRITICAL_WARNING:
return SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_CRITICAL_WARNING;
}
throw new IllegalArgumentException(
- String.format("Unexpected SafetySourceStatus.StatusLevel: %s",
- safetySourceStatusLevel));
+ String.format("Unexpected SafetySourceSeverity.Level in SafetySourceStatus: %s",
+ safetySourceSeverityLevel));
}
@SafetyCenterIssue.IssueSeverityLevel
private static int sourceToSafetyCenterIssueSeverityLevel(
- @SafetySourceIssue.SeverityLevel int safetySourceIssueSeverityLevel) {
+ @SafetySourceData.SeverityLevel int safetySourceIssueSeverityLevel) {
switch (safetySourceIssueSeverityLevel) {
- case SafetySourceIssue.SEVERITY_LEVEL_INFORMATION:
+ case SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED:
+ Log.w(TAG,
+ "Unexpected use of SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED in "
+ + "SafetySourceStatus");
+ return SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_OK;
+ case SafetySourceData.SEVERITY_LEVEL_INFORMATION:
return SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_OK;
- case SafetySourceIssue.SEVERITY_LEVEL_RECOMMENDATION:
+ case SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION:
return SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_RECOMMENDATION;
- case SafetySourceIssue.SEVERITY_LEVEL_CRITICAL_WARNING:
+ case SafetySourceData.SEVERITY_LEVEL_CRITICAL_WARNING:
return SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_CRITICAL_WARNING;
}
throw new IllegalArgumentException(
- String.format("Unexpected SafetySourceIssue.SeverityLevel: %s",
+ String.format("Unexpected SafetySourceSeverity.Level in SafetySourceIssue: %s",
safetySourceIssueSeverityLevel));
}
diff --git a/service/java/com/android/safetycenter/SafetyCenterRefreshManager.java b/service/java/com/android/safetycenter/SafetyCenterRefreshManager.java
index ff6085a96..d09ac2056 100644
--- a/service/java/com/android/safetycenter/SafetyCenterRefreshManager.java
+++ b/service/java/com/android/safetycenter/SafetyCenterRefreshManager.java
@@ -31,7 +31,6 @@ import static android.safetycenter.config.SafetySource.SAFETY_SOURCE_TYPE_STATIC
import android.annotation.NonNull;
import android.app.BroadcastOptions;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
@@ -66,7 +65,7 @@ final class SafetyCenterRefreshManager {
private static final Duration ALLOWLIST_DURATION = Duration.ofSeconds(20);
@NonNull
- private final List<ComponentName> mAdditionalSafetySourceBroadcastReceiverComponents =
+ private final List<String> mAdditionalSafetySourcePackageNames =
new ArrayList<>();
@NonNull
private final Context mContext;
@@ -84,18 +83,18 @@ final class SafetyCenterRefreshManager {
mSafetyCenterConfigReader = safetyCenterConfigReader;
}
- /** Adds a broadcast receiver component representing a source to refresh. */
+ /** Adds a package name representing a source to refresh. */
// TODO(b/218157907): Remove this method and use a SafetyCenterConfigReader field in
// SafetyCenterRefreshManager instead once ag/16834483 is submitted.
- void addAdditionalSafetySourceBroadcastReceiverComponent(@NonNull ComponentName componentName) {
- mAdditionalSafetySourceBroadcastReceiverComponents.add(componentName);
+ void addAdditionalSafetySourcePackageNames(@NonNull String packageName) {
+ mAdditionalSafetySourcePackageNames.add(packageName);
}
- /** Removes all additional broadcast receiver components representing sources to refresh. */
+ /** Removes all additional package names representing sources to refresh. */
// TODO(b/218157907): Remove this method and use a SafetyCenterConfigReader field in
// SafetyCenterRefreshManager instead once ag/16834483 is submitted.
- void clearAdditionalSafetySourceBroadcastReceiverComponents() {
- mAdditionalSafetySourceBroadcastReceiverComponents.clear();
+ void clearAdditionalSafetySourcePackageNames() {
+ mAdditionalSafetySourcePackageNames.clear();
}
/**
@@ -121,17 +120,14 @@ final class SafetyCenterRefreshManager {
return;
}
- // TODO(b/219702252): Use a more efficient data structure for this (and map broadcast
- // receiver to source ids).
+ // TODO(b/219702252): Use a more efficient data structure for this.
List<SafetySource> safetySourcesToRefresh =
safetyCenterConfig.getSafetySourcesGroups()
.stream()
.flatMap(group -> group.getSafetySources().stream())
.filter(
- // Only send broadcasts to dynamic safety sources that have
- // specified a broadcast receiver component.
- source -> source.getType() != SAFETY_SOURCE_TYPE_STATIC
- && source.getBroadcastReceiverClassName() != null)
+ // Only send broadcasts to dynamic safety sources.
+ source -> source.getType() != SAFETY_SOURCE_TYPE_STATIC)
.collect(Collectors.toList());
sendRefreshBroadcastToSafetySources(safetySourcesToRefresh, requestType);
@@ -152,9 +148,8 @@ final class SafetyCenterRefreshManager {
"Safety Center is requesting data from safety sources");
for (SafetySource source : safetySources) {
- Intent broadcastIntentForSource = new Intent(broadcastIntent).setComponent(
- new ComponentName(source.getPackageName(),
- source.getBroadcastReceiverClassName()));
+ Intent broadcastIntentForSource =
+ new Intent(broadcastIntent).setPackage(source.getPackageName());
// TODO(b/215144069): Add cross profile support for safety sources which support
// both personal and work profile. This implementation invokes
// `sendBroadcastAsUser` in order to invoke the permission.
@@ -178,9 +173,9 @@ final class SafetyCenterRefreshManager {
REASON_REFRESH_SAFETY_SOURCES,
"Safety Center is requesting data from safety sources");
- for (ComponentName componentName : mAdditionalSafetySourceBroadcastReceiverComponents) {
+ for (String packageName : mAdditionalSafetySourcePackageNames) {
// The following operation requires INTERACT_ACROSS_USERS permission.
- mContext.sendBroadcastAsUser(new Intent(broadcastIntent).setComponent(componentName),
+ mContext.sendBroadcastAsUser(new Intent(broadcastIntent).setPackage(packageName),
UserHandle.CURRENT,
SEND_SAFETY_CENTER_UPDATE,
broadcastOptions.toBundle());
diff --git a/service/java/com/android/safetycenter/SafetyCenterService.java b/service/java/com/android/safetycenter/SafetyCenterService.java
index 6096925b8..e246e9db4 100644
--- a/service/java/com/android/safetycenter/SafetyCenterService.java
+++ b/service/java/com/android/safetycenter/SafetyCenterService.java
@@ -29,7 +29,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.AppOpsManager;
-import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
@@ -231,6 +230,17 @@ public final class SafetyCenterService extends SystemService {
}
@Override
+ @Nullable
+ public SafetyCenterConfig getSafetyCenterConfig() {
+ getContext().enforceCallingOrSelfPermission(
+ MANAGE_SAFETY_CENTER, "getSafetyCenterConfig");
+
+ synchronized (mApiLock) {
+ return mSafetyCenterConfigReader.getSafetyCenterConfig();
+ }
+ }
+
+ @Override
@NonNull
public SafetyCenterData getSafetyCenterData(@UserIdInt int userId) {
// TODO(b/217235899): Finalize cross-user behavior.
@@ -320,10 +330,10 @@ public final class SafetyCenterService extends SystemService {
}
@Override
- public void clearAllSafetySourceData() {
+ public void clearAllSafetySourceDataForTests() {
getContext().enforceCallingOrSelfPermission(
- MANAGE_SAFETY_CENTER, "clearAllSafetySourceData");
- if (!checkApiEnabled("clearAllSafetySourceData")) {
+ MANAGE_SAFETY_CENTER, "clearAllSafetySourceDataForTests");
+ if (!checkApiEnabled("clearAllSafetySourceDataForTests")) {
return;
}
@@ -333,11 +343,11 @@ public final class SafetyCenterService extends SystemService {
}
@Override
- public void setSafetyCenterConfigOverride(
+ public void setSafetyCenterConfigForTests(
@NonNull SafetyCenterConfig safetyCenterConfig) {
getContext().enforceCallingOrSelfPermission(MANAGE_SAFETY_CENTER,
- "setSafetyCenterConfigOverride");
- if (!checkApiEnabled("setSafetyCenterConfigOverride")) {
+ "setSafetyCenterConfigForTests");
+ if (!checkApiEnabled("setSafetyCenterConfigForTests")) {
return;
}
@@ -349,14 +359,9 @@ public final class SafetyCenterService extends SystemService {
SafetySourcesGroup group = safetyCenterConfig.getSafetySourcesGroups().get(i);
for (int j = 0; j < group.getSafetySources().size(); j++) {
SafetySource safetySource = group.getSafetySources().get(j);
- if (safetySource.getType() != SAFETY_SOURCE_TYPE_STATIC
- && safetySource.getBroadcastReceiverClassName() != null) {
- mSafetyCenterRefreshManager
- .addAdditionalSafetySourceBroadcastReceiverComponent(
- new ComponentName(
- safetySource.getPackageName(),
- safetySource.getBroadcastReceiverClassName()
- ));
+ if (safetySource.getType() != SAFETY_SOURCE_TYPE_STATIC) {
+ mSafetyCenterRefreshManager.addAdditionalSafetySourcePackageNames(
+ safetySource.getPackageName());
}
}
}
@@ -364,16 +369,15 @@ public final class SafetyCenterService extends SystemService {
}
@Override
- public void clearSafetyCenterConfigOverride() {
+ public void clearSafetyCenterConfigForTests() {
getContext().enforceCallingOrSelfPermission(
- MANAGE_SAFETY_CENTER, "clearSafetyCenterConfigOverride");
- if (!checkApiEnabled("clearSafetyCenterConfigOverride")) {
+ MANAGE_SAFETY_CENTER, "clearSafetyCenterConfigForTests");
+ if (!checkApiEnabled("clearSafetyCenterConfigForTests")) {
return;
}
synchronized (mRefreshLock) {
- mSafetyCenterRefreshManager
- .clearAdditionalSafetySourceBroadcastReceiverComponents();
+ mSafetyCenterRefreshManager.clearAdditionalSafetySourcePackageNames();
}
}
diff --git a/tests/cts/safetycenter/Android.bp b/tests/cts/safetycenter/Android.bp
index f3b971635..a19827075 100644
--- a/tests/cts/safetycenter/Android.bp
+++ b/tests/cts/safetycenter/Android.bp
@@ -23,21 +23,22 @@ android_test {
defaults: ["mts-target-sdk-version-current"],
sdk_version: "test_current",
min_sdk_version: "30",
+ target_sdk_version: "32",
srcs: [
+ "src/**/*.java",
"src/**/*.kt",
],
static_libs: [
"androidx.test.core",
"androidx.test.ext.junit",
- "androidx.test.rules",
- "androidx.test.runner",
+ "androidx.test.ext.truth",
"androidx.test.uiautomator_uiautomator",
"compatibility-device-util-axt",
"ctstestrunner-axt",
+ "guava-android-testlib",
"kotlin-stdlib",
"kotlinx-coroutines-android",
"kotlin-test",
- "modules-utils-build_system",
"safety-center-resources-lib",
"truth-prebuilt",
],
diff --git a/tests/cts/safetycenter/AndroidManifest.xml b/tests/cts/safetycenter/AndroidManifest.xml
index 4a784753b..b01972a9a 100644
--- a/tests/cts/safetycenter/AndroidManifest.xml
+++ b/tests/cts/safetycenter/AndroidManifest.xml
@@ -18,7 +18,7 @@
package="android.safetycenter.cts">
<application>
- <receiver android:name="android.safetycenter.testing.SafetySourceBroadcastReceiver"
+ <receiver android:name=".testing.SafetySourceBroadcastReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.safetycenter.action.REFRESH_SAFETY_SOURCES"/>
diff --git a/tests/cts/safetycenter/AndroidTest.xml b/tests/cts/safetycenter/AndroidTest.xml
index fc74c4a71..3f76e6998 100644
--- a/tests/cts/safetycenter/AndroidTest.xml
+++ b/tests/cts/safetycenter/AndroidTest.xml
@@ -45,6 +45,7 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
<option name="package" value="android.safetycenter.cts"/>
+ <option name="exclude-annotation" value="org.junit.Ignore"/>
<option name="runtime-hint" value="5m"/>
</test>
</configuration>
diff --git a/tests/cts/safetycenter/OWNERS b/tests/cts/safetycenter/OWNERS
index 026d342a8..5d8b8161b 100644
--- a/tests/cts/safetycenter/OWNERS
+++ b/tests/cts/safetycenter/OWNERS
@@ -1,3 +1,3 @@
# Bug component: 1026964
-include platform/frameworks/base:/core/java/android/permission/OWNERS
+include /SafetyCenter/OWNERS
diff --git a/tests/cts/safetycenter/TEST_MAPPING b/tests/cts/safetycenter/TEST_MAPPING
new file mode 100644
index 000000000..3985e563c
--- /dev/null
+++ b/tests/cts/safetycenter/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsSafetyCenterTestCases"
+ }
+ ]
+}
diff --git a/tests/cts/safetycenter/res/xml/config_static_safety_source_with_broadcast.xml b/tests/cts/safetycenter/res/xml/config_static_safety_source_with_broadcast.xml
deleted file mode 100644
index 090bd5795..000000000
--- a/tests/cts/safetycenter/res/xml/config_static_safety_source_with_broadcast.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<safety-center-config>
- <safety-sources-config>
- <safety-sources-group
- id="id"
- title="@string/reference"
- summary="@string/reference">
- <static-safety-source
- id="id"
- title="@string/reference"
- summary="@string/reference"
- intentAction="intent"
- profile="primary_profile_only"
- broadcastReceiverClassName="broadcast"/>
- </safety-sources-group>
- </safety-sources-config>
-</safety-center-config>
diff --git a/tests/cts/safetycenter/res/xml/config_static_safety_source_with_notification.xml b/tests/cts/safetycenter/res/xml/config_static_safety_source_with_notification.xml
deleted file mode 100644
index 478fabd4d..000000000
--- a/tests/cts/safetycenter/res/xml/config_static_safety_source_with_notification.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<safety-center-config>
- <safety-sources-config>
- <safety-sources-group
- id="id"
- title="@string/reference"
- summary="@string/reference">
- <static-safety-source
- id="id"
- title="@string/reference"
- summary="@string/reference"
- intentAction="intent"
- profile="primary_profile_only"
- automaticNotificationFromIssueAllowed="true"/>
- </safety-sources-group>
- </safety-sources-config>
-</safety-center-config>
diff --git a/tests/cts/safetycenter/res/xml/config_valid.xml b/tests/cts/safetycenter/res/xml/config_valid.xml
index e25135b41..578ea1b72 100644
--- a/tests/cts/safetycenter/res/xml/config_valid.xml
+++ b/tests/cts/safetycenter/res/xml/config_valid.xml
@@ -23,10 +23,8 @@
initialDisplayState="disabled"
maxSeverityLevel="300"
searchTerms="@string/reference"
- broadcastReceiverClassName="broadcast"
loggingAllowed="false"
- refreshOnPageOpenAllowed="true"
- automaticNotificationFromIssueAllowed="true"/>
+ refreshOnPageOpenAllowed="true"/>
<dynamic-safety-source
id="dynamic_disabled"
packageName="package"
@@ -69,10 +67,8 @@
packageName="package"
profile="all_profiles"
maxSeverityLevel="300"
- broadcastReceiverClassName="broadcast"
loggingAllowed="false"
- refreshOnPageOpenAllowed="true"
- automaticNotificationFromIssueAllowed="true"/>
+ refreshOnPageOpenAllowed="true"/>
</safety-sources-group>
<safety-sources-group
id="mixed"
diff --git a/tests/cts/safetycenter/src/android/safetycenter/config/cts/ParserConfigInvalidTest.kt b/tests/cts/safetycenter/src/android/safetycenter/config/cts/ParserConfigInvalidTest.kt
deleted file mode 100644
index 0ef65ac20..000000000
--- a/tests/cts/safetycenter/src/android/safetycenter/config/cts/ParserConfigInvalidTest.kt
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.config.cts
-
-import android.content.Context
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.safetycenter.config.ParseException
-import android.safetycenter.config.SafetyCenterConfig
-import android.safetycenter.cts.R
-import androidx.test.core.app.ApplicationProvider.getApplicationContext
-import androidx.test.filters.SdkSuppress
-import com.google.common.truth.Truth.assertThat
-import org.junit.Assert.assertThrows
-import org.junit.Test
-import org.junit.runners.Parameterized
-import org.junit.runner.RunWith
-
-@RunWith(Parameterized::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class ParserConfigInvalidTest {
- private val context: Context = getApplicationContext()
-
- data class Params(
- private val testName: String,
- val configResourceId: Int,
- val errorMessage: String,
- val causeErrorMessage: String?
- ) {
- override fun toString() = testName
- }
-
- @Parameterized.Parameter
- lateinit var params: Params
-
- @Test
- fun invalidConfig_throws() {
- val parser = context.resources.getXml(params.configResourceId)
- val thrown = assertThrows(ParseException::class.java) {
- SafetyCenterConfig.fromXml(parser)
- }
- assertThat(thrown).hasMessageThat().isEqualTo(params.errorMessage)
- if (params.causeErrorMessage != null) {
- assertThat(thrown.cause).hasMessageThat().isEqualTo(params.causeErrorMessage)
- }
- }
-
- companion object {
- @JvmStatic
- @Parameterized.Parameters(name = "{0}")
- fun parameters() = arrayOf(
- Params(
- "ConfigDynamicSafetySourceAllDisabledNoWork",
- R.xml.config_dynamic_safety_source_all_disabled_no_work,
- "Element dynamic-safety-source invalid",
- "Required attribute titleForWork missing"
- ),
- Params(
- "ConfigDynamicSafetySourceAllNoWork",
- R.xml.config_dynamic_safety_source_all_no_work,
- "Element dynamic-safety-source invalid",
- "Required attribute titleForWork missing"
- ),
- Params(
- "ConfigDynamicSafetySourceDisabledNoSummary",
- R.xml.config_dynamic_safety_source_disabled_no_summary,
- "Element dynamic-safety-source invalid",
- "Required attribute summary missing"
- ),
- Params(
- "ConfigDynamicSafetySourceDisabledNoTitle",
- R.xml.config_dynamic_safety_source_disabled_no_title,
- "Element dynamic-safety-source invalid",
- "Required attribute title missing"
- ),
- Params(
- "ConfigDynamicSafetySourceDuplicateKey",
- R.xml.config_dynamic_safety_source_duplicate_key,
- "Element safety-sources-config invalid",
- "Duplicate id id among safety sources"
- ),
- Params(
- "ConfigDynamicSafetySourceHiddenWithIntent",
- R.xml.config_dynamic_safety_source_hidden_with_intent,
- "Element dynamic-safety-source invalid",
- "Prohibited attribute intentAction present"
- ),
- Params(
- "ConfigDynamicSafetySourceHiddenWithSummary",
- R.xml.config_dynamic_safety_source_hidden_with_summary,
- "Element dynamic-safety-source invalid",
- "Prohibited attribute summary present"
- ),
- Params(
- "ConfigDynamicSafetySourceHiddenWithTitle",
- R.xml.config_dynamic_safety_source_hidden_with_title,
- "Element dynamic-safety-source invalid",
- "Prohibited attribute title present"
- ),
- Params(
- "ConfigDynamicSafetySourceInvalidDisplay",
- R.xml.config_dynamic_safety_source_invalid_display,
- "Attribute dynamic-safety-source.initialDisplayState invalid",
- null
- ),
- Params(
- "ConfigDynamicSafetySourceInvalidProfile",
- R.xml.config_dynamic_safety_source_invalid_profile,
- "Attribute dynamic-safety-source.profile invalid",
- null
- ),
- Params(
- "ConfigDynamicSafetySourceNoId",
- R.xml.config_dynamic_safety_source_no_id,
- "Element dynamic-safety-source invalid",
- "Required attribute id missing"
- ),
- Params(
- "ConfigDynamicSafetySourceNoIntent",
- R.xml.config_dynamic_safety_source_no_intent,
- "Element dynamic-safety-source invalid",
- "Required attribute intentAction missing"
- ),
- Params(
- "ConfigDynamicSafetySourceNoPackage",
- R.xml.config_dynamic_safety_source_no_package,
- "Element dynamic-safety-source invalid",
- "Required attribute packageName missing"
- ),
- Params(
- "ConfigDynamicSafetySourceNoProfile",
- R.xml.config_dynamic_safety_source_no_profile,
- "Element dynamic-safety-source invalid",
- "Required attribute profile missing"
- ),
- Params(
- "ConfigDynamicSafetySourceNoSummary",
- R.xml.config_dynamic_safety_source_no_summary,
- "Element dynamic-safety-source invalid",
- "Required attribute summary missing"
- ),
- Params(
- "ConfigDynamicSafetySourceNoTitle",
- R.xml.config_dynamic_safety_source_no_title,
- "Element dynamic-safety-source invalid",
- "Required attribute title missing"
- ),
- Params(
- "ConfigDynamicSafetySourcePrimaryHiddenWithWork",
- R.xml.config_dynamic_safety_source_primary_hidden_with_work,
- "Element dynamic-safety-source invalid",
- "Prohibited attribute titleForWork present"
- ),
- Params(
- "ConfigDynamicSafetySourcePrimaryWithWork",
- R.xml.config_dynamic_safety_source_primary_with_work,
- "Element dynamic-safety-source invalid",
- "Prohibited attribute titleForWork present"
- ),
- Params(
- "ConfigIssueOnlySafetySourceDuplicateKey",
- R.xml.config_issue_only_safety_source_duplicate_key,
- "Element safety-sources-config invalid",
- "Duplicate id id among safety sources"
- ),
- Params(
- "ConfigIssueOnlySafetySourceInvalidProfile",
- R.xml.config_issue_only_safety_source_invalid_profile,
- "Attribute issue-only-safety-source.profile invalid",
- null
- ),
- Params(
- "ConfigIssueOnlySafetySourceNoId",
- R.xml.config_issue_only_safety_source_no_id,
- "Element issue-only-safety-source invalid",
- "Required attribute id missing"
- ),
- Params(
- "ConfigIssueOnlySafetySourceNoPackage",
- R.xml.config_issue_only_safety_source_no_package,
- "Element issue-only-safety-source invalid",
- "Required attribute packageName missing"
- ),
- Params(
- "ConfigIssueOnlySafetySourceNoProfile",
- R.xml.config_issue_only_safety_source_no_profile,
- "Element issue-only-safety-source invalid",
- "Required attribute profile missing"
- ),
- Params(
- "ConfigIssueOnlySafetySourceWithDisplay",
- R.xml.config_issue_only_safety_source_with_display,
- "Element issue-only-safety-source invalid",
- "Prohibited attribute initialDisplayState present"
- ),
- Params(
- "ConfigIssueOnlySafetySourceWithIntent",
- R.xml.config_issue_only_safety_source_with_intent,
- "Element issue-only-safety-source invalid",
- "Prohibited attribute intentAction present"
- ),
- Params(
- "ConfigIssueOnlySafetySourceWithSearch",
- R.xml.config_issue_only_safety_source_with_search,
- "Element issue-only-safety-source invalid",
- "Prohibited attribute searchTerms present"
- ),
- Params(
- "ConfigIssueOnlySafetySourceWithSummary",
- R.xml.config_issue_only_safety_source_with_summary,
- "Element issue-only-safety-source invalid",
- "Prohibited attribute summary present"
- ),
- Params(
- "ConfigIssueOnlySafetySourceWithTitle",
- R.xml.config_issue_only_safety_source_with_title,
- "Element issue-only-safety-source invalid",
- "Prohibited attribute title present"
- ),
- Params(
- "ConfigIssueOnlySafetySourceWithWork",
- R.xml.config_issue_only_safety_source_with_work,
- "Element issue-only-safety-source invalid",
- "Prohibited attribute titleForWork present"
- ),
- Params(
- "ConfigMixedSafetySourceDuplicateKey",
- R.xml.config_mixed_safety_source_duplicate_key,
- "Element safety-sources-config invalid",
- "Duplicate id id among safety sources"
- ),
- Params(
- "ConfigReferenceInvalid",
- R.xml.config_reference_invalid,
- "Reference title in safety-sources-group.title missing or invalid",
- null
- ),
- Params(
- "ConfigSafetyCenterConfigMissing",
- R.xml.config_safety_center_config_missing,
- "Element safety-center-config missing",
- null
- ),
- Params(
- "ConfigSafetySourcesConfigEmpty",
- R.xml.config_safety_sources_config_empty,
- "Element safety-sources-config invalid",
- "No safety sources groups present"
- ),
- Params(
- "ConfigSafetySourcesConfigMissing",
- R.xml.config_safety_sources_config_missing,
- "Element safety-sources-config missing",
- null
- ),
- Params(
- "ConfigSafetySourcesGroupDuplicateId",
- R.xml.config_safety_sources_group_duplicate_id,
- "Element safety-sources-config invalid",
- "Duplicate id id among safety sources groups"
- ),
- Params(
- "ConfigSafetySourcesGroupEmpty",
- R.xml.config_safety_sources_group_empty,
- "Element safety-sources-group invalid",
- "Safety sources group empty"
- ),
- Params(
- "ConfigSafetySourcesGroupInvalidIcon",
- R.xml.config_safety_sources_group_invalid_icon,
- "Attribute safety-sources-group.statelessIconType invalid",
- null
- ),
- Params(
- "ConfigSafetySourcesGroupNoId",
- R.xml.config_safety_sources_group_no_id,
- "Element safety-sources-group invalid",
- "Required attribute id missing"
- ),
- Params(
- "ConfigSafetySourcesGroupNoTitle",
- R.xml.config_safety_sources_group_no_title,
- "Element safety-sources-group invalid",
- "Required attribute title missing"
- ),
- Params(
- "ConfigStaticSafetySourceDuplicateKey",
- R.xml.config_static_safety_source_duplicate_key,
- "Element safety-sources-config invalid",
- "Duplicate id id among safety sources"
- ),
- Params(
- "ConfigStaticSafetySourceInvalidProfile",
- R.xml.config_static_safety_source_invalid_profile,
- "Attribute static-safety-source.profile invalid",
- null
- ),
- Params(
- "ConfigStaticSafetySourceNoId",
- R.xml.config_static_safety_source_no_id,
- "Element static-safety-source invalid",
- "Required attribute id missing"
- ),
- Params(
- "ConfigStaticSafetySourceNoIntent",
- R.xml.config_static_safety_source_no_intent,
- "Element static-safety-source invalid",
- "Required attribute intentAction missing"
- ),
- Params(
- "ConfigStaticSafetySourceNoProfile",
- R.xml.config_static_safety_source_no_profile,
- "Element static-safety-source invalid",
- "Required attribute profile missing"
- ),
- Params(
- "ConfigStaticSafetySourceNoSummary",
- R.xml.config_static_safety_source_no_summary,
- "Element static-safety-source invalid",
- "Required attribute summary missing"
- ),
- Params(
- "ConfigStaticSafetySourceNoTitle",
- R.xml.config_static_safety_source_no_title,
- "Element static-safety-source invalid",
- "Required attribute title missing"
- ),
- Params(
- "ConfigStaticSafetySourceWithBroadcast",
- R.xml.config_static_safety_source_with_broadcast,
- "Element static-safety-source invalid",
- "Prohibited attribute broadcastReceiverClassName present"
- ),
- Params(
- "ConfigStaticSafetySourceWithDisplay",
- R.xml.config_static_safety_source_with_display,
- "Element static-safety-source invalid",
- "Prohibited attribute initialDisplayState present"
- ),
- Params(
- "ConfigStaticSafetySourceWithLogging",
- R.xml.config_static_safety_source_with_logging,
- "Element static-safety-source invalid",
- "Prohibited attribute loggingAllowed present"
- ),
- Params(
- "ConfigStaticSafetySourceWithNotification",
- R.xml.config_static_safety_source_with_notification,
- "Element static-safety-source invalid",
- "Prohibited attribute automaticNotificationFromIssueAllowed present"
- ),
- Params(
- "ConfigStaticSafetySourceWithPackage",
- R.xml.config_static_safety_source_with_package,
- "Element static-safety-source invalid",
- "Prohibited attribute packageName present"
- ),
- Params(
- "ConfigStaticSafetySourceWithPrimaryAndWork",
- R.xml.config_static_safety_source_with_primary_and_work,
- "Element static-safety-source invalid",
- "Prohibited attribute titleForWork present"
- ),
- Params(
- "ConfigStaticSafetySourceWithRefresh",
- R.xml.config_static_safety_source_with_refresh,
- "Element static-safety-source invalid",
- "Prohibited attribute refreshOnPageOpenAllowed present"
- ),
- Params(
- "ConfigStaticSafetySourceWithSeverity",
- R.xml.config_static_safety_source_with_severity,
- "Element static-safety-source invalid",
- "Prohibited attribute maxSeverityLevel present"
- )
- )
- }
-}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/config/cts/ParserConfigValidTest.kt b/tests/cts/safetycenter/src/android/safetycenter/config/cts/ParserConfigValidTest.kt
deleted file mode 100644
index 299f7d9e7..000000000
--- a/tests/cts/safetycenter/src/android/safetycenter/config/cts/ParserConfigValidTest.kt
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.config.cts
-
-import android.content.Context
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.safetycenter.config.SafetyCenterConfig
-import android.safetycenter.config.SafetySource
-import android.safetycenter.config.SafetySourcesGroup
-import android.safetycenter.cts.R
-import androidx.test.core.app.ApplicationProvider.getApplicationContext
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class ParserConfigValidTest {
- private val context: Context = getApplicationContext()
-
- @Test
- fun validConfig_matchesExpected() {
- val parser = context.resources.getXml(R.xml.config_valid)
- val expected = SafetyCenterConfig.Builder()
- .addSafetySourcesGroup(SafetySourcesGroup.Builder()
- .setId("dynamic")
- .setTitleResId(R.string.reference)
- .setSummaryResId(R.string.reference)
- .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
- .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId("dynamic_barebone")
- .setPackageName("package")
- .setTitleResId(R.string.reference)
- .setSummaryResId(R.string.reference)
- .setIntentAction("intent")
- .setProfile(SafetySource.PROFILE_PRIMARY)
- .build())
- .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId("dynamic_all_optional")
- .setPackageName("package")
- .setTitleResId(R.string.reference)
- .setTitleForWorkResId(R.string.reference)
- .setSummaryResId(R.string.reference)
- .setIntentAction("intent")
- .setProfile(SafetySource.PROFILE_ALL)
- .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
- .setMaxSeverityLevel(300)
- .setSearchTermsResId(R.string.reference)
- .setBroadcastReceiverClassName("broadcast")
- .setLoggingAllowed(false)
- .setRefreshOnPageOpenAllowed(true)
- .setAutomaticNotificationFromIssueAllowed(true)
- .build())
- .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId("dynamic_disabled")
- .setPackageName("package")
- .setTitleResId(R.string.reference)
- .setSummaryResId(R.string.reference)
- .setProfile(SafetySource.PROFILE_PRIMARY)
- .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
- .build())
- .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId("dynamic_hidden")
- .setPackageName("package")
- .setProfile(SafetySource.PROFILE_ALL)
- .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
- .build())
- .build())
- .addSafetySourcesGroup(SafetySourcesGroup.Builder()
- .setId("static")
- .setTitleResId(R.string.reference)
- .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_STATIC)
- .setId("static_barebone")
- .setTitleResId(R.string.reference)
- .setSummaryResId(R.string.reference)
- .setIntentAction("intent")
- .setProfile(SafetySource.PROFILE_PRIMARY)
- .build())
- .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_STATIC)
- .setId("static_all_optional")
- .setTitleResId(R.string.reference)
- .setTitleForWorkResId(R.string.reference)
- .setSummaryResId(R.string.reference)
- .setIntentAction("intent")
- .setProfile(SafetySource.PROFILE_ALL)
- .setSearchTermsResId(R.string.reference)
- .build())
- .build())
- .addSafetySourcesGroup(SafetySourcesGroup.Builder()
- .setId("issue_only")
- .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY)
- .setId("issue_only_barebone")
- .setPackageName("package")
- .setProfile(SafetySource.PROFILE_PRIMARY)
- .build())
- .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY)
- .setId("issue_only_all_optional")
- .setPackageName("package")
- .setProfile(SafetySource.PROFILE_ALL)
- .setMaxSeverityLevel(300)
- .setBroadcastReceiverClassName("broadcast")
- .setLoggingAllowed(false)
- .setRefreshOnPageOpenAllowed(true)
- .setAutomaticNotificationFromIssueAllowed(true)
- .build())
- .build())
- .addSafetySourcesGroup(SafetySourcesGroup.Builder()
- .setId("mixed")
- .setTitleResId(R.string.reference)
- .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId("mixed_dynamic_barebone")
- .setPackageName("package")
- .setTitleResId(R.string.reference)
- .setSummaryResId(R.string.reference)
- .setIntentAction("intent")
- .setProfile(SafetySource.PROFILE_PRIMARY)
- .build())
- .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY)
- .setId("mixed_issue_only_barebone")
- .setPackageName("package")
- .setProfile(SafetySource.PROFILE_PRIMARY)
- .build())
- .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_STATIC)
- .setId("mixed_static_barebone")
- .setTitleResId(R.string.reference)
- .setSummaryResId(R.string.reference)
- .setIntentAction("intent")
- .setProfile(SafetySource.PROFILE_PRIMARY)
- .build())
- .build())
- .build()
- assertThat(SafetyCenterConfig.fromXml(parser)).isEqualTo(expected)
- }
-}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/config/cts/SafetyCenterConfigTest.kt b/tests/cts/safetycenter/src/android/safetycenter/config/cts/SafetyCenterConfigTest.kt
deleted file mode 100644
index c42192ed8..000000000
--- a/tests/cts/safetycenter/src/android/safetycenter/config/cts/SafetyCenterConfigTest.kt
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.config.cts
-
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.safetycenter.config.SafetyCenterConfig
-import android.safetycenter.testing.AnyTester
-import android.safetycenter.testing.ParcelableTester
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-/** CTS tests for [SafetyCenterConfig]. */
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class SafetyCenterConfigTest {
- @Test
- fun getSafetySources_returnsSafetySources() {
- assertThat(BASE.safetySourcesGroups)
- .containsExactly(
- SafetySourcesGroupTest.RIGID,
- SafetySourcesGroupTest.HIDDEN
- ).inOrder()
- }
-
- @Test
- fun describeContents_returns0() {
- assertThat(BASE.describeContents()).isEqualTo(0)
- }
-
- @Test
- fun createFromParcel_withWriteToParcel_returnsOriginalSafetyCenterConfig() {
- ParcelableTester.assertThatRoundTripReturnsOriginal(BASE, SafetyCenterConfig.CREATOR)
- }
-
- // TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
- @Test
- fun hashCode_equals_toString_withEqualByReference_areEqual() {
- AnyTester.assertThatRepresentationsAreEqual(BASE, BASE)
- }
-
- @Test
- fun hashCode_equals_toString_withAllFieldsEqual_areEqual() {
- val baseAlt = SafetyCenterConfig.Builder()
- .addSafetySourcesGroup(SafetySourcesGroupTest.RIGID)
- .addSafetySourcesGroup(SafetySourcesGroupTest.HIDDEN)
- .build()
- AnyTester.assertThatRepresentationsAreEqual(BASE, baseAlt)
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentSafetySources_areNotEqual() {
- val baseAlt = SafetyCenterConfig.Builder()
- .addSafetySourcesGroup(SafetySourcesGroupTest.HIDDEN)
- .addSafetySourcesGroup(SafetySourcesGroupTest.RIGID)
- .build()
- AnyTester.assertThatRepresentationsAreNotEqual(BASE, baseAlt)
- }
-
- companion object {
- private val BASE = SafetyCenterConfig.Builder()
- .addSafetySourcesGroup(SafetySourcesGroupTest.RIGID)
- .addSafetySourcesGroup(SafetySourcesGroupTest.HIDDEN)
- .build()
- }
-}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/config/cts/SafetySourceTest.kt b/tests/cts/safetycenter/src/android/safetycenter/config/cts/SafetySourceTest.kt
deleted file mode 100644
index 830de10f4..000000000
--- a/tests/cts/safetycenter/src/android/safetycenter/config/cts/SafetySourceTest.kt
+++ /dev/null
@@ -1,751 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.config.cts
-
-import android.content.res.Resources
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.safetycenter.config.SafetySource
-import android.safetycenter.testing.AnyTester
-import android.safetycenter.testing.ParcelableTester
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.google.common.truth.Truth.assertThat
-import org.junit.Assert.assertThrows
-import org.junit.Test
-import org.junit.runner.RunWith
-
-/** CTS tests for [SafetySource]. */
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class SafetySourceTest {
- @Test
- fun getType_returnsType() {
- assertThat(DYNAMIC_BAREBONE.type).isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- assertThat(DYNAMIC_ALL_OPTIONAL.type).isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- assertThat(DYNAMIC_HIDDEN.type).isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- assertThat(DYNAMIC_DISABLED.type).isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- assertThat(STATIC_BAREBONE.type).isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_STATIC)
- assertThat(STATIC_ALL_OPTIONAL.type).isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_STATIC)
- assertThat(ISSUE_ONLY_BAREBONE.type).isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY)
- assertThat(ISSUE_ONLY_ALL_OPTIONAL.type)
- .isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY)
- }
-
- @Test
- fun getId_returnsId() {
- assertThat(DYNAMIC_BAREBONE.id).isEqualTo(DYNAMIC_BAREBONE_ID)
- assertThat(DYNAMIC_ALL_OPTIONAL.id).isEqualTo(DYNAMIC_ALL_OPTIONAL_ID)
- assertThat(DYNAMIC_HIDDEN.id).isEqualTo(DYNAMIC_HIDDEN_ID)
- assertThat(DYNAMIC_DISABLED.id).isEqualTo(DYNAMIC_DISABLED_ID)
- assertThat(STATIC_BAREBONE.id).isEqualTo(STATIC_BAREBONE_ID)
- assertThat(STATIC_ALL_OPTIONAL.id).isEqualTo(STATIC_ALL_OPTIONAL_ID)
- assertThat(ISSUE_ONLY_BAREBONE.id).isEqualTo(ISSUE_ONLY_BAREBONE_ID)
- assertThat(ISSUE_ONLY_ALL_OPTIONAL.id).isEqualTo(ISSUE_ONLY_ALL_OPTIONAL_ID)
- }
-
- @Test
- fun getPackageName_returnsPackageNameOrThrows() {
- assertThat(DYNAMIC_BAREBONE.packageName).isEqualTo(PACKAGE_NAME)
- assertThat(DYNAMIC_ALL_OPTIONAL.packageName).isEqualTo(PACKAGE_NAME)
- assertThat(DYNAMIC_HIDDEN.packageName).isEqualTo(PACKAGE_NAME)
- assertThat(DYNAMIC_DISABLED.packageName).isEqualTo(PACKAGE_NAME)
- assertThrows(UnsupportedOperationException::class.java) {
- STATIC_BAREBONE.packageName
- }
- assertThrows(UnsupportedOperationException::class.java) {
- STATIC_ALL_OPTIONAL.packageName
- }
- assertThat(ISSUE_ONLY_BAREBONE.packageName).isEqualTo(PACKAGE_NAME)
- assertThat(ISSUE_ONLY_ALL_OPTIONAL.packageName).isEqualTo(PACKAGE_NAME)
- }
-
- @Test
- fun getTitleResId_returnsTitleResIdOrThrows() {
- assertThat(DYNAMIC_BAREBONE.titleResId).isEqualTo(REFERENCE_RES_ID)
- assertThat(DYNAMIC_ALL_OPTIONAL.titleResId).isEqualTo(REFERENCE_RES_ID)
- assertThat(DYNAMIC_DISABLED.titleResId).isEqualTo(REFERENCE_RES_ID)
- assertThat(DYNAMIC_HIDDEN.titleResId).isEqualTo(Resources.ID_NULL)
- assertThat(STATIC_BAREBONE.titleResId).isEqualTo(REFERENCE_RES_ID)
- assertThat(STATIC_ALL_OPTIONAL.titleResId).isEqualTo(REFERENCE_RES_ID)
- assertThrows(UnsupportedOperationException::class.java) {
- ISSUE_ONLY_BAREBONE.titleResId
- }
- assertThrows(UnsupportedOperationException::class.java) {
- ISSUE_ONLY_ALL_OPTIONAL.titleResId
- }
- }
-
- @Test
- fun getTitleForWorkResId_returnsTitleForWorkResIdOrThrows() {
- assertThrows(UnsupportedOperationException::class.java) {
- DYNAMIC_BAREBONE.titleForWorkResId
- }
- assertThat(DYNAMIC_ALL_OPTIONAL.titleForWorkResId).isEqualTo(REFERENCE_RES_ID)
- assertThrows(UnsupportedOperationException::class.java) {
- DYNAMIC_DISABLED.titleForWorkResId
- }
- assertThat(DYNAMIC_HIDDEN.titleForWorkResId).isEqualTo(Resources.ID_NULL)
- assertThrows(UnsupportedOperationException::class.java) {
- STATIC_BAREBONE.titleForWorkResId
- }
- assertThat(STATIC_ALL_OPTIONAL.titleForWorkResId).isEqualTo(REFERENCE_RES_ID)
- assertThrows(UnsupportedOperationException::class.java) {
- ISSUE_ONLY_BAREBONE.titleForWorkResId
- }
- assertThrows(UnsupportedOperationException::class.java) {
- ISSUE_ONLY_ALL_OPTIONAL.titleForWorkResId
- }
- }
-
- @Test
- fun getSummaryResId_returnsSummaryResIdOrThrows() {
- assertThat(DYNAMIC_BAREBONE.summaryResId).isEqualTo(REFERENCE_RES_ID)
- assertThat(DYNAMIC_ALL_OPTIONAL.summaryResId).isEqualTo(REFERENCE_RES_ID)
- assertThat(DYNAMIC_DISABLED.summaryResId).isEqualTo(REFERENCE_RES_ID)
- assertThat(DYNAMIC_HIDDEN.summaryResId).isEqualTo(Resources.ID_NULL)
- assertThat(STATIC_BAREBONE.summaryResId).isEqualTo(REFERENCE_RES_ID)
- assertThat(STATIC_ALL_OPTIONAL.summaryResId).isEqualTo(REFERENCE_RES_ID)
- assertThrows(UnsupportedOperationException::class.java) {
- ISSUE_ONLY_BAREBONE.summaryResId
- }
- assertThrows(UnsupportedOperationException::class.java) {
- ISSUE_ONLY_ALL_OPTIONAL.summaryResId
- }
- }
-
- @Test
- fun getIntentAction_returnsIntentActionOrThrows() {
- assertThat(DYNAMIC_BAREBONE.intentAction).isEqualTo(INTENT_ACTION)
- assertThat(DYNAMIC_ALL_OPTIONAL.intentAction).isEqualTo(INTENT_ACTION)
- assertThat(DYNAMIC_DISABLED.intentAction).isNull()
- assertThat(DYNAMIC_HIDDEN.intentAction).isNull()
- assertThat(STATIC_BAREBONE.intentAction).isEqualTo(INTENT_ACTION)
- assertThat(STATIC_ALL_OPTIONAL.intentAction).isEqualTo(INTENT_ACTION)
- assertThrows(UnsupportedOperationException::class.java) {
- ISSUE_ONLY_BAREBONE.intentAction
- }
- assertThrows(UnsupportedOperationException::class.java) {
- ISSUE_ONLY_ALL_OPTIONAL.intentAction
- }
- }
-
- @Test
- fun getProfile_returnsProfile() {
- assertThat(DYNAMIC_BAREBONE.profile).isEqualTo(SafetySource.PROFILE_PRIMARY)
- assertThat(DYNAMIC_ALL_OPTIONAL.profile).isEqualTo(SafetySource.PROFILE_ALL)
- assertThat(DYNAMIC_DISABLED.profile).isEqualTo(SafetySource.PROFILE_PRIMARY)
- assertThat(DYNAMIC_HIDDEN.profile).isEqualTo(SafetySource.PROFILE_ALL)
- assertThat(STATIC_BAREBONE.profile).isEqualTo(SafetySource.PROFILE_PRIMARY)
- assertThat(STATIC_ALL_OPTIONAL.profile).isEqualTo(SafetySource.PROFILE_ALL)
- assertThat(ISSUE_ONLY_BAREBONE.profile).isEqualTo(SafetySource.PROFILE_PRIMARY)
- assertThat(ISSUE_ONLY_ALL_OPTIONAL.profile).isEqualTo(SafetySource.PROFILE_ALL)
- }
-
- @Test
- fun getInitialDisplayState_returnsInitialDisplayStateOrThrows() {
- assertThat(DYNAMIC_BAREBONE.initialDisplayState)
- .isEqualTo(SafetySource.INITIAL_DISPLAY_STATE_ENABLED)
- assertThat(DYNAMIC_ALL_OPTIONAL.initialDisplayState)
- .isEqualTo(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
- assertThat(DYNAMIC_DISABLED.initialDisplayState)
- .isEqualTo(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
- assertThat(DYNAMIC_HIDDEN.initialDisplayState)
- .isEqualTo(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
- assertThrows(UnsupportedOperationException::class.java) {
- STATIC_BAREBONE.initialDisplayState
- }
- assertThrows(UnsupportedOperationException::class.java) {
- STATIC_ALL_OPTIONAL.initialDisplayState
- }
- assertThrows(UnsupportedOperationException::class.java) {
- ISSUE_ONLY_BAREBONE.initialDisplayState
- }
- assertThrows(UnsupportedOperationException::class.java) {
- ISSUE_ONLY_ALL_OPTIONAL.initialDisplayState
- }
- }
-
- @Test
- fun getMaxSeverityLevel_returnsMaxSeverityLevelOrThrows() {
- assertThat(DYNAMIC_BAREBONE.maxSeverityLevel).isEqualTo(Integer.MAX_VALUE)
- assertThat(DYNAMIC_ALL_OPTIONAL.maxSeverityLevel).isEqualTo(MAX_SEVERITY_LEVEL)
- assertThat(DYNAMIC_DISABLED.maxSeverityLevel).isEqualTo(Integer.MAX_VALUE)
- assertThat(DYNAMIC_HIDDEN.maxSeverityLevel).isEqualTo(Integer.MAX_VALUE)
- assertThrows(UnsupportedOperationException::class.java) {
- STATIC_BAREBONE.maxSeverityLevel
- }
- assertThrows(UnsupportedOperationException::class.java) {
- STATIC_ALL_OPTIONAL.maxSeverityLevel
- }
- assertThat(ISSUE_ONLY_BAREBONE.maxSeverityLevel).isEqualTo(Integer.MAX_VALUE)
- assertThat(ISSUE_ONLY_ALL_OPTIONAL.maxSeverityLevel).isEqualTo(MAX_SEVERITY_LEVEL)
- }
-
- @Test
- fun getSearchTermsResId_returnsSearchTermsResIdOrThrows() {
- assertThat(DYNAMIC_BAREBONE.searchTermsResId).isEqualTo(Resources.ID_NULL)
- assertThat(DYNAMIC_ALL_OPTIONAL.searchTermsResId).isEqualTo(REFERENCE_RES_ID)
- assertThat(DYNAMIC_DISABLED.searchTermsResId).isEqualTo(Resources.ID_NULL)
- assertThat(DYNAMIC_HIDDEN.searchTermsResId).isEqualTo(Resources.ID_NULL)
- assertThat(STATIC_BAREBONE.searchTermsResId).isEqualTo(Resources.ID_NULL)
- assertThat(STATIC_ALL_OPTIONAL.searchTermsResId).isEqualTo(REFERENCE_RES_ID)
- assertThrows(UnsupportedOperationException::class.java) {
- ISSUE_ONLY_BAREBONE.searchTermsResId
- }
- assertThrows(UnsupportedOperationException::class.java) {
- ISSUE_ONLY_ALL_OPTIONAL.searchTermsResId
- }
- }
-
- @Test
- fun getBroadcastReceiverClassName_returnsBroadcastReceiverClassNameOrThrows() {
- assertThat(DYNAMIC_BAREBONE.broadcastReceiverClassName).isNull()
- assertThat(DYNAMIC_ALL_OPTIONAL.broadcastReceiverClassName)
- .isEqualTo(BROADCAST_RECEIVER_CLASS_NAME)
- assertThat(DYNAMIC_DISABLED.broadcastReceiverClassName).isNull()
- assertThat(DYNAMIC_HIDDEN.broadcastReceiverClassName).isNull()
- assertThrows(UnsupportedOperationException::class.java) {
- STATIC_BAREBONE.broadcastReceiverClassName
- }
- assertThrows(UnsupportedOperationException::class.java) {
- STATIC_ALL_OPTIONAL.broadcastReceiverClassName
- }
- assertThat(ISSUE_ONLY_BAREBONE.broadcastReceiverClassName).isNull()
- assertThat(ISSUE_ONLY_ALL_OPTIONAL.broadcastReceiverClassName)
- .isEqualTo(BROADCAST_RECEIVER_CLASS_NAME)
- }
-
- @Test
- fun isLoggingAllowed_returnsLoggingAllowedOrThrows() {
- assertThat(DYNAMIC_BAREBONE.isLoggingAllowed).isEqualTo(true)
- assertThat(DYNAMIC_ALL_OPTIONAL.isLoggingAllowed).isEqualTo(false)
- assertThat(DYNAMIC_DISABLED.isLoggingAllowed).isEqualTo(true)
- assertThat(DYNAMIC_HIDDEN.isLoggingAllowed).isEqualTo(true)
- assertThrows(UnsupportedOperationException::class.java) {
- STATIC_BAREBONE.isLoggingAllowed
- }
- assertThrows(UnsupportedOperationException::class.java) {
- STATIC_ALL_OPTIONAL.isLoggingAllowed
- }
- assertThat(ISSUE_ONLY_BAREBONE.isLoggingAllowed).isEqualTo(true)
- assertThat(ISSUE_ONLY_ALL_OPTIONAL.isLoggingAllowed).isEqualTo(false)
- }
-
- @Test
- fun isRefreshOnPageOpenAllowed_returnsRefreshOnPageOpenAllowedOrThrows() {
- assertThat(DYNAMIC_BAREBONE.isRefreshOnPageOpenAllowed).isEqualTo(false)
- assertThat(DYNAMIC_ALL_OPTIONAL.isRefreshOnPageOpenAllowed).isEqualTo(true)
- assertThat(DYNAMIC_DISABLED.isRefreshOnPageOpenAllowed).isEqualTo(false)
- assertThat(DYNAMIC_HIDDEN.isRefreshOnPageOpenAllowed).isEqualTo(false)
- assertThrows(UnsupportedOperationException::class.java) {
- STATIC_BAREBONE.isRefreshOnPageOpenAllowed
- }
- assertThrows(UnsupportedOperationException::class.java) {
- STATIC_ALL_OPTIONAL.isRefreshOnPageOpenAllowed
- }
- assertThat(ISSUE_ONLY_BAREBONE.isRefreshOnPageOpenAllowed).isEqualTo(false)
- assertThat(ISSUE_ONLY_ALL_OPTIONAL.isRefreshOnPageOpenAllowed).isEqualTo(true)
- }
-
- @Test
- fun isAutomaticNotificationFromIssueAllowed_returnsAutoNotificationFromIssueAllowedOrThrows() {
- assertThat(DYNAMIC_BAREBONE.isAutomaticNotificationFromIssueAllowed).isEqualTo(false)
- assertThat(DYNAMIC_ALL_OPTIONAL.isAutomaticNotificationFromIssueAllowed).isEqualTo(true)
- assertThat(DYNAMIC_DISABLED.isAutomaticNotificationFromIssueAllowed).isEqualTo(false)
- assertThat(DYNAMIC_HIDDEN.isAutomaticNotificationFromIssueAllowed).isEqualTo(false)
- assertThrows(UnsupportedOperationException::class.java) {
- STATIC_BAREBONE.isAutomaticNotificationFromIssueAllowed
- }
- assertThrows(UnsupportedOperationException::class.java) {
- STATIC_ALL_OPTIONAL.isAutomaticNotificationFromIssueAllowed
- }
- assertThat(ISSUE_ONLY_BAREBONE.isAutomaticNotificationFromIssueAllowed).isEqualTo(false)
- assertThat(ISSUE_ONLY_ALL_OPTIONAL.isAutomaticNotificationFromIssueAllowed).isEqualTo(true)
- }
-
- @Test
- fun describeContents_returns0() {
- assertThat(DYNAMIC_BAREBONE.describeContents()).isEqualTo(0)
- assertThat(DYNAMIC_ALL_OPTIONAL.describeContents()).isEqualTo(0)
- assertThat(DYNAMIC_HIDDEN.describeContents()).isEqualTo(0)
- assertThat(DYNAMIC_DISABLED.describeContents()).isEqualTo(0)
- assertThat(STATIC_BAREBONE.describeContents()).isEqualTo(0)
- assertThat(STATIC_ALL_OPTIONAL.describeContents()).isEqualTo(0)
- assertThat(ISSUE_ONLY_BAREBONE.describeContents()).isEqualTo(0)
- assertThat(ISSUE_ONLY_ALL_OPTIONAL.describeContents()).isEqualTo(0)
- }
-
- @Test
- fun createFromParcel_withWriteToParcel_returnsOriginalSafetySource() {
- ParcelableTester.assertThatRoundTripReturnsOriginal(DYNAMIC_BAREBONE, SafetySource.CREATOR)
- ParcelableTester.assertThatRoundTripReturnsOriginal(
- DYNAMIC_ALL_OPTIONAL,
- SafetySource.CREATOR
- )
- ParcelableTester.assertThatRoundTripReturnsOriginal(DYNAMIC_HIDDEN, SafetySource.CREATOR)
- ParcelableTester.assertThatRoundTripReturnsOriginal(DYNAMIC_DISABLED, SafetySource.CREATOR)
- ParcelableTester.assertThatRoundTripReturnsOriginal(STATIC_BAREBONE, SafetySource.CREATOR)
- ParcelableTester.assertThatRoundTripReturnsOriginal(
- STATIC_ALL_OPTIONAL,
- SafetySource.CREATOR
- )
- ParcelableTester.assertThatRoundTripReturnsOriginal(
- ISSUE_ONLY_BAREBONE,
- SafetySource.CREATOR
- )
- ParcelableTester.assertThatRoundTripReturnsOriginal(
- ISSUE_ONLY_ALL_OPTIONAL,
- SafetySource.CREATOR
- )
- }
-
- // TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
- @Test
- fun hashCode_equals_toString_withEqualByReference_areEqual() {
- AnyTester.assertThatRepresentationsAreEqual(DYNAMIC_BAREBONE, DYNAMIC_BAREBONE)
- AnyTester.assertThatRepresentationsAreEqual(DYNAMIC_ALL_OPTIONAL, DYNAMIC_ALL_OPTIONAL)
- AnyTester.assertThatRepresentationsAreEqual(DYNAMIC_HIDDEN, DYNAMIC_HIDDEN)
- AnyTester.assertThatRepresentationsAreEqual(DYNAMIC_DISABLED, DYNAMIC_DISABLED)
- AnyTester.assertThatRepresentationsAreEqual(STATIC_BAREBONE, STATIC_BAREBONE)
- AnyTester.assertThatRepresentationsAreEqual(STATIC_ALL_OPTIONAL, STATIC_ALL_OPTIONAL)
- AnyTester.assertThatRepresentationsAreEqual(ISSUE_ONLY_BAREBONE, ISSUE_ONLY_BAREBONE)
- AnyTester.assertThatRepresentationsAreEqual(
- ISSUE_ONLY_ALL_OPTIONAL,
- ISSUE_ONLY_ALL_OPTIONAL
- )
- }
-
- @Test
- fun hashCode_equals_toString_withAllFieldsEqual_areEqual() {
- val dynamicAllOptionalCopy = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId(DYNAMIC_ALL_OPTIONAL_ID)
- .setPackageName(PACKAGE_NAME)
- .setTitleResId(REFERENCE_RES_ID)
- .setTitleForWorkResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setIntentAction(INTENT_ACTION)
- .setProfile(SafetySource.PROFILE_ALL)
- .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
- .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
- .setSearchTermsResId(REFERENCE_RES_ID)
- .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setLoggingAllowed(false)
- .setRefreshOnPageOpenAllowed(true)
- .setAutomaticNotificationFromIssueAllowed(true)
- .build()
- AnyTester.assertThatRepresentationsAreEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalCopy)
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentTypes_areNotEqual() {
- AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_BAREBONE, STATIC_BAREBONE)
- AnyTester.assertThatRepresentationsAreNotEqual(STATIC_BAREBONE, ISSUE_ONLY_BAREBONE)
- AnyTester.assertThatRepresentationsAreNotEqual(ISSUE_ONLY_BAREBONE, DYNAMIC_BAREBONE)
- AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, STATIC_ALL_OPTIONAL)
- AnyTester.assertThatRepresentationsAreNotEqual(STATIC_ALL_OPTIONAL, ISSUE_ONLY_ALL_OPTIONAL)
- AnyTester.assertThatRepresentationsAreNotEqual(
- ISSUE_ONLY_ALL_OPTIONAL,
- DYNAMIC_ALL_OPTIONAL
- )
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentIds_areNotEqual() {
- val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId("other")
- .setPackageName(PACKAGE_NAME)
- .setTitleResId(REFERENCE_RES_ID)
- .setTitleForWorkResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setIntentAction(INTENT_ACTION)
- .setProfile(SafetySource.PROFILE_ALL)
- .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
- .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
- .setSearchTermsResId(REFERENCE_RES_ID)
- .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setLoggingAllowed(false)
- .setRefreshOnPageOpenAllowed(true)
- .setAutomaticNotificationFromIssueAllowed(true)
- .build()
- AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentPackageNames_areNotEqual() {
- val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId(DYNAMIC_ALL_OPTIONAL_ID)
- .setPackageName("other")
- .setTitleResId(REFERENCE_RES_ID)
- .setTitleForWorkResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setIntentAction(INTENT_ACTION)
- .setProfile(SafetySource.PROFILE_ALL)
- .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
- .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
- .setSearchTermsResId(REFERENCE_RES_ID)
- .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setLoggingAllowed(false)
- .setRefreshOnPageOpenAllowed(true)
- .setAutomaticNotificationFromIssueAllowed(true)
- .build()
- AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentTitleResIds_areNotEqual() {
- val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId(DYNAMIC_ALL_OPTIONAL_ID)
- .setPackageName(PACKAGE_NAME)
- .setTitleResId(-1)
- .setTitleForWorkResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setIntentAction(INTENT_ACTION)
- .setProfile(SafetySource.PROFILE_ALL)
- .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
- .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
- .setSearchTermsResId(REFERENCE_RES_ID)
- .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setLoggingAllowed(false)
- .setRefreshOnPageOpenAllowed(true)
- .setAutomaticNotificationFromIssueAllowed(true)
- .build()
- AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentTitleForWorkResIds_areNotEqual() {
- val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId(DYNAMIC_ALL_OPTIONAL_ID)
- .setPackageName(PACKAGE_NAME)
- .setTitleResId(REFERENCE_RES_ID)
- .setTitleForWorkResId(-1)
- .setSummaryResId(REFERENCE_RES_ID)
- .setIntentAction(INTENT_ACTION)
- .setProfile(SafetySource.PROFILE_ALL)
- .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
- .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
- .setSearchTermsResId(REFERENCE_RES_ID)
- .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setLoggingAllowed(false)
- .setRefreshOnPageOpenAllowed(true)
- .setAutomaticNotificationFromIssueAllowed(true)
- .build()
- AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentSummaryResIds_areNotEqual() {
- val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId(DYNAMIC_ALL_OPTIONAL_ID)
- .setPackageName(PACKAGE_NAME)
- .setTitleResId(REFERENCE_RES_ID)
- .setTitleForWorkResId(REFERENCE_RES_ID)
- .setSummaryResId(-1)
- .setIntentAction(INTENT_ACTION)
- .setProfile(SafetySource.PROFILE_ALL)
- .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
- .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
- .setSearchTermsResId(REFERENCE_RES_ID)
- .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setLoggingAllowed(false)
- .setRefreshOnPageOpenAllowed(true)
- .setAutomaticNotificationFromIssueAllowed(true)
- .build()
- AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentIntentActions_areNotEqual() {
- val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId(DYNAMIC_ALL_OPTIONAL_ID)
- .setPackageName(PACKAGE_NAME)
- .setTitleResId(REFERENCE_RES_ID)
- .setTitleForWorkResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setIntentAction("other")
- .setProfile(SafetySource.PROFILE_ALL)
- .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
- .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
- .setSearchTermsResId(REFERENCE_RES_ID)
- .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setLoggingAllowed(false)
- .setRefreshOnPageOpenAllowed(true)
- .setAutomaticNotificationFromIssueAllowed(true)
- .build()
- AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentProfiles_areNotEqual() {
- val dynamicHiddenAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId(DYNAMIC_HIDDEN_ID)
- .setPackageName(PACKAGE_NAME)
- .setProfile(SafetySource.PROFILE_PRIMARY)
- .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
- .build()
- AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_HIDDEN, dynamicHiddenAlt)
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentInitialDisplayStates_areNotEqual() {
- val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId(DYNAMIC_ALL_OPTIONAL_ID)
- .setPackageName(PACKAGE_NAME)
- .setTitleResId(REFERENCE_RES_ID)
- .setTitleForWorkResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setIntentAction(INTENT_ACTION)
- .setProfile(SafetySource.PROFILE_ALL)
- .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_ENABLED)
- .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
- .setSearchTermsResId(REFERENCE_RES_ID)
- .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setLoggingAllowed(false)
- .setRefreshOnPageOpenAllowed(true)
- .setAutomaticNotificationFromIssueAllowed(true)
- .build()
- AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentMaxSeverityLevel_areNotEqual() {
- val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId(DYNAMIC_ALL_OPTIONAL_ID)
- .setPackageName(PACKAGE_NAME)
- .setTitleResId(REFERENCE_RES_ID)
- .setTitleForWorkResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setIntentAction(INTENT_ACTION)
- .setProfile(SafetySource.PROFILE_ALL)
- .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
- .setMaxSeverityLevel(-1)
- .setSearchTermsResId(REFERENCE_RES_ID)
- .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setLoggingAllowed(false)
- .setRefreshOnPageOpenAllowed(true)
- .setAutomaticNotificationFromIssueAllowed(true)
- .build()
- AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentSearchTermsResIds_areNotEqual() {
- val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId(DYNAMIC_ALL_OPTIONAL_ID)
- .setPackageName(PACKAGE_NAME)
- .setTitleResId(REFERENCE_RES_ID)
- .setTitleForWorkResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setIntentAction(INTENT_ACTION)
- .setProfile(SafetySource.PROFILE_ALL)
- .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
- .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
- .setSearchTermsResId(-1)
- .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setLoggingAllowed(false)
- .setRefreshOnPageOpenAllowed(true)
- .setAutomaticNotificationFromIssueAllowed(true)
- .build()
- AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentBroadcastReceiverClassNames_areNotEqual() {
- val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId(DYNAMIC_ALL_OPTIONAL_ID)
- .setPackageName(PACKAGE_NAME)
- .setTitleResId(REFERENCE_RES_ID)
- .setTitleForWorkResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setIntentAction(INTENT_ACTION)
- .setProfile(SafetySource.PROFILE_ALL)
- .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
- .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
- .setSearchTermsResId(REFERENCE_RES_ID)
- .setBroadcastReceiverClassName("other")
- .setLoggingAllowed(false)
- .setRefreshOnPageOpenAllowed(true)
- .setAutomaticNotificationFromIssueAllowed(true)
- .build()
- AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentLoggingAllowed_areNotEqual() {
- val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId(DYNAMIC_ALL_OPTIONAL_ID)
- .setPackageName(PACKAGE_NAME)
- .setTitleResId(REFERENCE_RES_ID)
- .setTitleForWorkResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setIntentAction(INTENT_ACTION)
- .setProfile(SafetySource.PROFILE_ALL)
- .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
- .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
- .setSearchTermsResId(REFERENCE_RES_ID)
- .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setLoggingAllowed(true)
- .setRefreshOnPageOpenAllowed(true)
- .setAutomaticNotificationFromIssueAllowed(true)
- .build()
- AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentRefreshOnPageOpenAllowed_areNotEqual() {
- val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId(DYNAMIC_ALL_OPTIONAL_ID)
- .setPackageName(PACKAGE_NAME)
- .setTitleResId(REFERENCE_RES_ID)
- .setTitleForWorkResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setIntentAction(INTENT_ACTION)
- .setProfile(SafetySource.PROFILE_ALL)
- .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
- .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
- .setSearchTermsResId(REFERENCE_RES_ID)
- .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setLoggingAllowed(false)
- .setRefreshOnPageOpenAllowed(false)
- .setAutomaticNotificationFromIssueAllowed(true)
- .build()
- AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentAutomaticNotificationFromIssueAllowed_areNotEqual() {
- val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId(DYNAMIC_ALL_OPTIONAL_ID)
- .setPackageName(PACKAGE_NAME)
- .setTitleResId(REFERENCE_RES_ID)
- .setTitleForWorkResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setIntentAction(INTENT_ACTION)
- .setProfile(SafetySource.PROFILE_ALL)
- .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
- .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
- .setSearchTermsResId(REFERENCE_RES_ID)
- .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setLoggingAllowed(false)
- .setRefreshOnPageOpenAllowed(true)
- .setAutomaticNotificationFromIssueAllowed(false)
- .build()
- AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
- }
-
- companion object {
- private const val PACKAGE_NAME = "package"
- private const val REFERENCE_RES_ID = 9999
- private const val INTENT_ACTION = "intent"
- private const val BROADCAST_RECEIVER_CLASS_NAME = "broadcast"
- private const val MAX_SEVERITY_LEVEL = 300
-
- private const val DYNAMIC_BAREBONE_ID = "dynamic_barebone"
- private const val DYNAMIC_ALL_OPTIONAL_ID = "dynamic_all_optional"
- private const val DYNAMIC_DISABLED_ID = "dynamic_disabled"
- private const val DYNAMIC_HIDDEN_ID = "dynamic_hidden"
- private const val STATIC_BAREBONE_ID = "static_barebone"
- private const val STATIC_ALL_OPTIONAL_ID = "static_all_optional"
- private const val ISSUE_ONLY_BAREBONE_ID = "issue_only_barebone"
- private const val ISSUE_ONLY_ALL_OPTIONAL_ID = "issue_only_all_optional"
-
- internal val DYNAMIC_BAREBONE =
- SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId(DYNAMIC_BAREBONE_ID)
- .setPackageName(PACKAGE_NAME)
- .setTitleResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setIntentAction(INTENT_ACTION)
- .setProfile(SafetySource.PROFILE_PRIMARY)
- .build()
-
- private val DYNAMIC_ALL_OPTIONAL =
- SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId(DYNAMIC_ALL_OPTIONAL_ID)
- .setPackageName(PACKAGE_NAME)
- .setTitleResId(REFERENCE_RES_ID)
- .setTitleForWorkResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setIntentAction(INTENT_ACTION)
- .setProfile(SafetySource.PROFILE_ALL)
- .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
- .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
- .setSearchTermsResId(REFERENCE_RES_ID)
- .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setLoggingAllowed(false)
- .setRefreshOnPageOpenAllowed(true)
- .setAutomaticNotificationFromIssueAllowed(true)
- .build()
-
- private val DYNAMIC_DISABLED =
- SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId(DYNAMIC_DISABLED_ID)
- .setPackageName(PACKAGE_NAME)
- .setTitleResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setProfile(SafetySource.PROFILE_PRIMARY)
- .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
- .build()
-
- private val DYNAMIC_HIDDEN =
- SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
- .setId(DYNAMIC_HIDDEN_ID)
- .setPackageName(PACKAGE_NAME)
- .setProfile(SafetySource.PROFILE_ALL)
- .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
- .build()
-
- internal val STATIC_BAREBONE =
- SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_STATIC)
- .setId(STATIC_BAREBONE_ID)
- .setTitleResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setIntentAction(INTENT_ACTION)
- .setProfile(SafetySource.PROFILE_PRIMARY)
- .build()
-
- private val STATIC_ALL_OPTIONAL =
- SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_STATIC)
- .setId(STATIC_ALL_OPTIONAL_ID)
- .setTitleResId(REFERENCE_RES_ID)
- .setTitleForWorkResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setIntentAction(INTENT_ACTION)
- .setProfile(SafetySource.PROFILE_ALL)
- .setSearchTermsResId(REFERENCE_RES_ID)
- .build()
-
- internal val ISSUE_ONLY_BAREBONE =
- SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY)
- .setId(ISSUE_ONLY_BAREBONE_ID)
- .setPackageName(PACKAGE_NAME)
- .setProfile(SafetySource.PROFILE_PRIMARY)
- .build()
-
- private val ISSUE_ONLY_ALL_OPTIONAL =
- SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY)
- .setId(ISSUE_ONLY_ALL_OPTIONAL_ID)
- .setPackageName(PACKAGE_NAME)
- .setProfile(SafetySource.PROFILE_ALL)
- .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
- .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setLoggingAllowed(false)
- .setRefreshOnPageOpenAllowed(true)
- .setAutomaticNotificationFromIssueAllowed(true)
- .build()
- }
-}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/config/cts/SafetySourcesGroupTest.kt b/tests/cts/safetycenter/src/android/safetycenter/config/cts/SafetySourcesGroupTest.kt
deleted file mode 100644
index 09c0de91f..000000000
--- a/tests/cts/safetycenter/src/android/safetycenter/config/cts/SafetySourcesGroupTest.kt
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.config.cts
-
-import android.content.res.Resources
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.safetycenter.config.SafetySourcesGroup
-import android.safetycenter.testing.AnyTester
-import android.safetycenter.testing.ParcelableTester
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-/** CTS tests for [SafetySourcesGroup]. */
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class SafetySourcesGroupTest {
- @Test
- fun getType_returnsType() {
- assertThat(COLLAPSIBLE_WITH_SUMMARY.type)
- .isEqualTo(SafetySourcesGroup.SAFETY_SOURCES_GROUP_TYPE_COLLAPSIBLE)
- assertThat(COLLAPSIBLE_WITH_ICON.type)
- .isEqualTo(SafetySourcesGroup.SAFETY_SOURCES_GROUP_TYPE_COLLAPSIBLE)
- assertThat(COLLAPSIBLE_WITH_BOTH.type)
- .isEqualTo(SafetySourcesGroup.SAFETY_SOURCES_GROUP_TYPE_COLLAPSIBLE)
- assertThat(RIGID.type).isEqualTo(SafetySourcesGroup.SAFETY_SOURCES_GROUP_TYPE_RIGID)
- assertThat(HIDDEN.type).isEqualTo(SafetySourcesGroup.SAFETY_SOURCES_GROUP_TYPE_HIDDEN)
- }
-
- @Test
- fun getId_returnsId() {
- assertThat(COLLAPSIBLE_WITH_SUMMARY.id).isEqualTo(COLLAPSIBLE_WITH_SUMMARY_ID)
- assertThat(COLLAPSIBLE_WITH_ICON.id).isEqualTo(COLLAPSIBLE_WITH_ICON_ID)
- assertThat(COLLAPSIBLE_WITH_BOTH.id).isEqualTo(COLLAPSIBLE_WITH_BOTH_ID)
- assertThat(RIGID.id).isEqualTo(RIGID_ID)
- assertThat(HIDDEN.id).isEqualTo(HIDDEN_ID)
- }
-
- @Test
- fun getTitleResId_returnsTitleResId() {
- assertThat(COLLAPSIBLE_WITH_SUMMARY.titleResId).isEqualTo(REFERENCE_RES_ID)
- assertThat(COLLAPSIBLE_WITH_ICON.titleResId).isEqualTo(REFERENCE_RES_ID)
- assertThat(COLLAPSIBLE_WITH_BOTH.titleResId).isEqualTo(REFERENCE_RES_ID)
- assertThat(RIGID.titleResId).isEqualTo(REFERENCE_RES_ID)
- // This is not an enforced invariant, titleResId should just be ignored for hidden groups
- assertThat(HIDDEN.titleResId).isEqualTo(Resources.ID_NULL)
- }
-
- @Test
- fun getSummaryResId_returnsSummaryResId() {
- assertThat(COLLAPSIBLE_WITH_SUMMARY.summaryResId).isEqualTo(REFERENCE_RES_ID)
- assertThat(COLLAPSIBLE_WITH_ICON.summaryResId).isEqualTo(Resources.ID_NULL)
- assertThat(COLLAPSIBLE_WITH_BOTH.summaryResId).isEqualTo(REFERENCE_RES_ID)
- assertThat(RIGID.summaryResId).isEqualTo(Resources.ID_NULL)
- // This is not an enforced invariant, summaryResId should just be ignored for hidden groups
- assertThat(HIDDEN.summaryResId).isEqualTo(Resources.ID_NULL)
- }
-
- @Test
- fun getStatelessIconType_returnsStatelessIconType() {
- assertThat(COLLAPSIBLE_WITH_SUMMARY.statelessIconType)
- .isEqualTo(SafetySourcesGroup.STATELESS_ICON_TYPE_NONE)
- assertThat(COLLAPSIBLE_WITH_ICON.statelessIconType)
- .isEqualTo(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
- assertThat(COLLAPSIBLE_WITH_BOTH.statelessIconType)
- .isEqualTo(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
- assertThat(RIGID.statelessIconType).isEqualTo(SafetySourcesGroup.STATELESS_ICON_TYPE_NONE)
- // This is not an enforced invariant
- // statelessIconType should just be ignored for hidden groups
- assertThat(HIDDEN.statelessIconType).isEqualTo(SafetySourcesGroup.STATELESS_ICON_TYPE_NONE)
- }
-
- @Test
- fun getSafetySources_returnsSafetySources() {
- assertThat(COLLAPSIBLE_WITH_SUMMARY.safetySources)
- .containsExactly(SafetySourceTest.DYNAMIC_BAREBONE)
- assertThat(COLLAPSIBLE_WITH_ICON.safetySources)
- .containsExactly(SafetySourceTest.STATIC_BAREBONE)
- assertThat(COLLAPSIBLE_WITH_BOTH.safetySources)
- .containsExactly(
- SafetySourceTest.DYNAMIC_BAREBONE,
- SafetySourceTest.STATIC_BAREBONE,
- SafetySourceTest.ISSUE_ONLY_BAREBONE
- ).inOrder()
- assertThat(RIGID.safetySources).containsExactly(SafetySourceTest.STATIC_BAREBONE)
- assertThat(HIDDEN.safetySources).containsExactly(SafetySourceTest.ISSUE_ONLY_BAREBONE)
- }
-
- @Test
- fun describeContents_returns0() {
- assertThat(COLLAPSIBLE_WITH_SUMMARY.describeContents()).isEqualTo(0)
- assertThat(COLLAPSIBLE_WITH_ICON.describeContents()).isEqualTo(0)
- assertThat(COLLAPSIBLE_WITH_BOTH.describeContents()).isEqualTo(0)
- assertThat(RIGID.describeContents()).isEqualTo(0)
- assertThat(HIDDEN.describeContents()).isEqualTo(0)
- }
-
- @Test
- fun createFromParcel_withWriteToParcel_returnsOriginalSafetySourcesGroup() {
- ParcelableTester.assertThatRoundTripReturnsOriginal(
- COLLAPSIBLE_WITH_SUMMARY,
- SafetySourcesGroup.CREATOR
- )
- ParcelableTester.assertThatRoundTripReturnsOriginal(
- COLLAPSIBLE_WITH_ICON,
- SafetySourcesGroup.CREATOR
- )
- ParcelableTester.assertThatRoundTripReturnsOriginal(
- COLLAPSIBLE_WITH_BOTH,
- SafetySourcesGroup.CREATOR
- )
- ParcelableTester.assertThatRoundTripReturnsOriginal(RIGID, SafetySourcesGroup.CREATOR)
- ParcelableTester.assertThatRoundTripReturnsOriginal(HIDDEN, SafetySourcesGroup.CREATOR)
- }
-
- // TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
- @Test
- fun hashCode_equals_toString_withEqualByReference_areEqual() {
- AnyTester.assertThatRepresentationsAreEqual(
- COLLAPSIBLE_WITH_SUMMARY,
- COLLAPSIBLE_WITH_SUMMARY
- )
- AnyTester.assertThatRepresentationsAreEqual(COLLAPSIBLE_WITH_ICON, COLLAPSIBLE_WITH_ICON)
- AnyTester.assertThatRepresentationsAreEqual(COLLAPSIBLE_WITH_BOTH, COLLAPSIBLE_WITH_BOTH)
- AnyTester.assertThatRepresentationsAreEqual(RIGID, RIGID)
- AnyTester.assertThatRepresentationsAreEqual(HIDDEN, HIDDEN)
- }
-
- @Test
- fun hashCode_equals_toString_withAllFieldsEqual_areEqual() {
- val collapsibleWithBothCopy = SafetySourcesGroup.Builder()
- .setId(COLLAPSIBLE_WITH_BOTH_ID)
- .setTitleResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
- .addSafetySource(SafetySourceTest.DYNAMIC_BAREBONE)
- .addSafetySource(SafetySourceTest.STATIC_BAREBONE)
- .addSafetySource(SafetySourceTest.ISSUE_ONLY_BAREBONE)
- .build()
- AnyTester.assertThatRepresentationsAreEqual(COLLAPSIBLE_WITH_BOTH, collapsibleWithBothCopy)
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentTypes_areNotEqual() {
- AnyTester.assertThatRepresentationsAreNotEqual(COLLAPSIBLE_WITH_BOTH, RIGID)
- AnyTester.assertThatRepresentationsAreNotEqual(RIGID, HIDDEN)
- AnyTester.assertThatRepresentationsAreNotEqual(HIDDEN, COLLAPSIBLE_WITH_BOTH)
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentIds_areNotEqual() {
- val collapsibleWithBothAlt = SafetySourcesGroup.Builder()
- .setId("other")
- .setTitleResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
- .addSafetySource(SafetySourceTest.DYNAMIC_BAREBONE)
- .build()
- AnyTester.assertThatRepresentationsAreNotEqual(
- COLLAPSIBLE_WITH_BOTH,
- collapsibleWithBothAlt
- )
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentTitleResIds_areNotEqual() {
- val collapsibleWithBothAlt = SafetySourcesGroup.Builder()
- .setId(COLLAPSIBLE_WITH_BOTH_ID)
- .setTitleResId(-1)
- .setSummaryResId(REFERENCE_RES_ID)
- .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
- .addSafetySource(SafetySourceTest.DYNAMIC_BAREBONE)
- .build()
- AnyTester.assertThatRepresentationsAreNotEqual(
- COLLAPSIBLE_WITH_BOTH,
- collapsibleWithBothAlt
- )
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentSummaryResIds_areNotEqual() {
- val collapsibleWithBothAlt = SafetySourcesGroup.Builder()
- .setId(COLLAPSIBLE_WITH_BOTH_ID)
- .setTitleResId(REFERENCE_RES_ID)
- .setSummaryResId(-1)
- .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
- .addSafetySource(SafetySourceTest.DYNAMIC_BAREBONE)
- .build()
- AnyTester.assertThatRepresentationsAreNotEqual(
- COLLAPSIBLE_WITH_BOTH,
- collapsibleWithBothAlt
- )
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentInitialDisplayStates_areNotEqual() {
- val collapsibleWithBothAlt = SafetySourcesGroup.Builder()
- .setId(COLLAPSIBLE_WITH_BOTH_ID)
- .setTitleResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_NONE)
- .addSafetySource(SafetySourceTest.DYNAMIC_BAREBONE)
- .build()
- AnyTester.assertThatRepresentationsAreNotEqual(
- COLLAPSIBLE_WITH_BOTH,
- collapsibleWithBothAlt
- )
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentSafetySources_areNotEqual() {
- val collapsibleWithBothAlt = SafetySourcesGroup.Builder()
- .setId(COLLAPSIBLE_WITH_BOTH_ID)
- .setTitleResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
- .addSafetySource(SafetySourceTest.STATIC_BAREBONE)
- .build()
- AnyTester.assertThatRepresentationsAreNotEqual(
- COLLAPSIBLE_WITH_BOTH,
- collapsibleWithBothAlt
- )
- }
-
- companion object {
- private const val REFERENCE_RES_ID = 9999
-
- private const val COLLAPSIBLE_WITH_SUMMARY_ID = "collapsible_with_summary"
- private const val COLLAPSIBLE_WITH_ICON_ID = "collapsible_with_icon"
- private const val COLLAPSIBLE_WITH_BOTH_ID = "collapsible_with_both"
- private const val RIGID_ID = "rigid"
- private const val HIDDEN_ID = "hidden"
-
- private val COLLAPSIBLE_WITH_SUMMARY = SafetySourcesGroup.Builder()
- .setId(COLLAPSIBLE_WITH_SUMMARY_ID)
- .setTitleResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .addSafetySource(SafetySourceTest.DYNAMIC_BAREBONE)
- .build()
-
- private val COLLAPSIBLE_WITH_ICON = SafetySourcesGroup.Builder()
- .setId(COLLAPSIBLE_WITH_ICON_ID)
- .setTitleResId(REFERENCE_RES_ID)
- .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
- .addSafetySource(SafetySourceTest.STATIC_BAREBONE)
- .build()
-
- private val COLLAPSIBLE_WITH_BOTH = SafetySourcesGroup.Builder()
- .setId(COLLAPSIBLE_WITH_BOTH_ID)
- .setTitleResId(REFERENCE_RES_ID)
- .setSummaryResId(REFERENCE_RES_ID)
- .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
- .addSafetySource(SafetySourceTest.DYNAMIC_BAREBONE)
- .addSafetySource(SafetySourceTest.STATIC_BAREBONE)
- .addSafetySource(SafetySourceTest.ISSUE_ONLY_BAREBONE)
- .build()
-
- internal val RIGID = SafetySourcesGroup.Builder()
- .setId(RIGID_ID)
- .setTitleResId(REFERENCE_RES_ID)
- .addSafetySource(SafetySourceTest.STATIC_BAREBONE)
- .build()
-
- internal val HIDDEN = SafetySourcesGroup.Builder()
- .setId(HIDDEN_ID)
- .addSafetySource(SafetySourceTest.ISSUE_ONLY_BAREBONE)
- .build()
- }
-}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterActivityTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterActivityTest.kt
index 57a1c2c71..40524a5d8 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterActivityTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterActivityTest.kt
@@ -20,8 +20,8 @@ import android.content.Context
import android.content.Intent
import android.content.Intent.ACTION_SAFETY_CENTER
import android.os.Build.VERSION_CODES.TIRAMISU
-import android.safetycenter.testing.SafetyCenterFlags
-import android.safetycenter.testing.SafetyCenterFlags.deviceSupportsSafetyCenter
+import android.safetycenter.cts.testing.SafetyCenterFlags
+import android.safetycenter.cts.testing.SafetyCenterFlags.deviceSupportsSafetyCenter
import android.support.test.uiautomator.By
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterDataTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterDataTest.kt
index 5d3df8995..65a6c370e 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterDataTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterDataTest.kt
@@ -20,7 +20,6 @@ import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
import android.safetycenter.SafetyCenterData
import android.safetycenter.SafetyCenterEntry
import android.safetycenter.SafetyCenterEntryGroup
@@ -29,84 +28,82 @@ import android.safetycenter.SafetyCenterIssue
import android.safetycenter.SafetyCenterStaticEntry
import android.safetycenter.SafetyCenterStaticEntryGroup
import android.safetycenter.SafetyCenterStatus
+import android.safetycenter.cts.testing.EqualsHashCodeToStringTester
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.ext.truth.os.ParcelableSubject.assertThat
import androidx.test.filters.SdkSuppress
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
+import kotlin.test.assertFailsWith
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
class SafetyCenterDataTest {
private val context: Context = ApplicationProvider.getApplicationContext()
- private val pendingIntent = PendingIntent.getActivity(
- context,
- /* requestCode= */ 0,
- Intent("Fake Data"),
- PendingIntent.FLAG_IMMUTABLE)
+ private val pendingIntent =
+ PendingIntent.getActivity(context, 0, Intent("Fake Data"), PendingIntent.FLAG_IMMUTABLE)
- val status1 = SafetyCenterStatus.Builder()
- .setTitle("This is my title")
- .setSummary("This is my summary")
+ private val status1 =
+ SafetyCenterStatus.Builder("This is my title", "This is my summary")
.setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_RECOMMENDATION)
.build()
- val status2 = SafetyCenterStatus.Builder()
- .setTitle("This is also my title")
- .setSummary("This is also my summary")
+ private val status2 =
+ SafetyCenterStatus.Builder("This is also my title", "This is also my summary")
.setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK)
.build()
- val issue1 = SafetyCenterIssue.Builder("iSsUe_iD_oNe")
- .setTitle("An issue title")
- .setSummary("An issue summary")
+ private val issue1 =
+ SafetyCenterIssue.Builder("iSsUe_iD_oNe", "An issue title", "An issue summary")
.setSeverityLevel(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_OK)
.build()
- val issue2 = SafetyCenterIssue.Builder("iSsUe_iD_tWo")
- .setTitle("Another issue title")
- .setSummary("Another issue summary")
+ private val issue2 =
+ SafetyCenterIssue.Builder("iSsUe_iD_tWo", "Another issue title", "Another issue summary")
.setSeverityLevel(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_RECOMMENDATION)
.build()
- val entry1 = SafetyCenterEntry.Builder("eNtRy_iD_OnE")
- .setTitle("An entry title")
+ private val entry1 =
+ SafetyCenterEntry.Builder("eNtRy_iD_OnE", "An entry title")
.setPendingIntent(pendingIntent)
.setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
.build()
- val entry2 = SafetyCenterEntry.Builder("eNtRy_iD_TwO")
- .setTitle("Another entry title")
+ private val entry2 =
+ SafetyCenterEntry.Builder("eNtRy_iD_TwO", "Another entry title")
.setPendingIntent(pendingIntent)
.setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
.build()
- val entryGroup1 = SafetyCenterEntryGroup.Builder("eNtRy_gRoUp_iD")
- .setTitle("An entry group title")
+ private val entryGroup1 =
+ SafetyCenterEntryGroup.Builder("eNtRy_gRoUp_iD", "An entry group title")
.setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
.setEntries(listOf(entry2))
.build()
- val entryOrGroup1 = SafetyCenterEntryOrGroup(entry1)
- val entryOrGroup2 = SafetyCenterEntryOrGroup(entryGroup1)
+ private val entryOrGroup1 = SafetyCenterEntryOrGroup(entry1)
+ private val entryOrGroup2 = SafetyCenterEntryOrGroup(entryGroup1)
- val staticEntry1 = SafetyCenterStaticEntry(
- "A static entry title",
- "A static entry summary",
- pendingIntent)
- val staticEntry2 = SafetyCenterStaticEntry(
- "Another static entry title",
- "Another static entry summary",
- pendingIntent)
+ private val staticEntry1 =
+ SafetyCenterStaticEntry.Builder("A static entry title")
+ .setSummary("A static entry summary")
+ .setPendingIntent(pendingIntent)
+ .build()
+ private val staticEntry2 =
+ SafetyCenterStaticEntry.Builder("Another static entry title")
+ .setSummary("Another static entry summary")
+ .setPendingIntent(pendingIntent)
+ .build()
- val staticEntryGroup1 = SafetyCenterStaticEntryGroup(
- "A static entry group title", listOf(staticEntry1))
- val staticEntryGroup2 = SafetyCenterStaticEntryGroup(
- "Another static entry group title", listOf(staticEntry2))
+ private val staticEntryGroup1 =
+ SafetyCenterStaticEntryGroup("A static entry group title", listOf(staticEntry1))
+ private val staticEntryGroup2 =
+ SafetyCenterStaticEntryGroup("Another static entry group title", listOf(staticEntry2))
- val data1 = SafetyCenterData(
- status1, listOf(issue1), listOf(entryOrGroup1), listOf(staticEntryGroup1))
- val data2 = SafetyCenterData(
- status2, listOf(issue2), listOf(entryOrGroup2), listOf(staticEntryGroup2))
+ private val data1 =
+ SafetyCenterData(status1, listOf(issue1), listOf(entryOrGroup1), listOf(staticEntryGroup1))
+ private val data2 =
+ SafetyCenterData(status2, listOf(issue2), listOf(entryOrGroup2), listOf(staticEntryGroup2))
@Test
fun getStatus_returnsStatus() {
@@ -121,12 +118,10 @@ class SafetyCenterDataTest {
}
@Test
- fun getIssues_mutationsAreNotReflected() {
+ fun getIssues_mutationsAreNotAllowed() {
val mutatedIssues = data1.issues
- mutatedIssues.add(issue2)
- assertThat(mutatedIssues).containsExactly(issue1, issue2)
- assertThat(data1.issues).doesNotContain(issue2)
+ assertFailsWith(UnsupportedOperationException::class) { mutatedIssues.add(issue2) }
}
@Test
@@ -136,12 +131,12 @@ class SafetyCenterDataTest {
}
@Test
- fun getEntriesOrGroups_mutationsAreNotReflected() {
+ fun getEntriesOrGroups_mutationsAreNotAllowed() {
val mutatedEntriesOrGroups = data1.entriesOrGroups
- mutatedEntriesOrGroups.add(entryOrGroup2)
- assertThat(mutatedEntriesOrGroups).containsExactly(entryOrGroup1, entryOrGroup2)
- assertThat(data1.entriesOrGroups).doesNotContain(entryOrGroup2)
+ assertFailsWith(UnsupportedOperationException::class) {
+ mutatedEntriesOrGroups.add(entryOrGroup2)
+ }
}
@Test
@@ -151,101 +146,59 @@ class SafetyCenterDataTest {
}
@Test
- fun getStaticEntryGroups_mutationsAreNotReflected() {
+ fun getStaticEntryGroups_mutationsAreNotAllowed() {
val mutatedStaticEntryGroups = data1.staticEntryGroups
- mutatedStaticEntryGroups.add(staticEntryGroup2)
- assertThat(mutatedStaticEntryGroups).containsExactly(staticEntryGroup1, staticEntryGroup2)
- assertThat(data1.staticEntryGroups).doesNotContain(staticEntryGroup2)
+ assertFailsWith(UnsupportedOperationException::class) {
+ mutatedStaticEntryGroups.add(staticEntryGroup2)
+ }
}
@Test
fun describeContents_returns0() {
assertThat(data1.describeContents()).isEqualTo(0)
- }
-
- @Test
- fun createFromParcel_withWriteToParcel_returnsEquivalentObject() {
- val parcel: Parcel = Parcel.obtain()
-
- data1.writeToParcel(parcel, 0 /* flags */)
- parcel.setDataPosition(0)
- val fromParcel = SafetyCenterData.CREATOR.createFromParcel(parcel)
- parcel.recycle()
-
- assertThat(fromParcel).isEqualTo(data1)
- }
-
- @Test
- fun equals_hashCode_toString_equalByReference_areEqual() {
- assertThat(data1).isEqualTo(data1)
- assertThat(data1.hashCode()).isEqualTo(data1.hashCode())
- assertThat(data1.toString()).isEqualTo(data1.toString())
- }
-
- @Test
- fun equals_hashCode_toString_equalByValue_areEqual() {
- val data = SafetyCenterData(
- status1, listOf(issue1), listOf(entryOrGroup1), listOf(staticEntryGroup1))
- val equivalentData = SafetyCenterData(
- status1, listOf(issue1), listOf(entryOrGroup1), listOf(staticEntryGroup1))
-
- assertThat(data).isEqualTo(equivalentData)
- assertThat(data.hashCode()).isEqualTo(equivalentData.hashCode())
- assertThat(data.toString()).isEqualTo(equivalentData.toString())
- }
-
- @Test
- fun equals_hashCode_toString_withEmptyLists_equalByValue_areEqual() {
- val data = SafetyCenterData(status1, listOf(), listOf(), listOf())
- val equivalentData = SafetyCenterData(status1, listOf(), listOf(), listOf())
-
- assertThat(data).isEqualTo(equivalentData)
- assertThat(data.hashCode()).isEqualTo(equivalentData.hashCode())
- assertThat(data.toString()).isEqualTo(equivalentData.toString())
- }
-
- @Test
- fun equals_toString_withDifferentStatuses_areNotEqual() {
- val data = SafetyCenterData(
- status1, listOf(issue1), listOf(entryOrGroup1), listOf(staticEntryGroup1))
- val differentData = SafetyCenterData(
- status2, listOf(issue1), listOf(entryOrGroup1), listOf(staticEntryGroup1))
-
- assertThat(data).isNotEqualTo(differentData)
- assertThat(data.toString()).isNotEqualTo(differentData.toString())
- }
-
- @Test
- fun equals_toString_withDifferentIssues_areNotEqual() {
- val data = SafetyCenterData(
- status1, listOf(issue1), listOf(entryOrGroup1), listOf(staticEntryGroup1))
- val differentData = SafetyCenterData(
- status1, listOf(issue2), listOf(entryOrGroup1), listOf(staticEntryGroup1))
-
- assertThat(data).isNotEqualTo(differentData)
- assertThat(data.toString()).isNotEqualTo(differentData.toString())
- }
-
- @Test
- fun equals_toString_withDifferentEntriesOrGroups_areNotEqual() {
- val data = SafetyCenterData(
- status1, listOf(issue1), listOf(entryOrGroup1), listOf(staticEntryGroup1))
- val differentData = SafetyCenterData(
- status1, listOf(issue1), listOf(entryOrGroup2), listOf(staticEntryGroup1))
-
- assertThat(data).isNotEqualTo(differentData)
- assertThat(data.toString()).isNotEqualTo(differentData.toString())
- }
-
- @Test
- fun equals_toString_withDifferentStaticEntryGroups_areNotEqual() {
- val data = SafetyCenterData(
- status1, listOf(issue1), listOf(entryOrGroup1), listOf(staticEntryGroup1))
- val differentData = SafetyCenterData(
- status1, listOf(issue1), listOf(entryOrGroup1), listOf(staticEntryGroup2))
-
- assertThat(data).isNotEqualTo(differentData)
- assertThat(data.toString()).isNotEqualTo(differentData.toString())
- }
-} \ No newline at end of file
+ assertThat(data2.describeContents()).isEqualTo(0)
+ }
+
+ @Test
+ fun parcelRoundTrip_recreatesEqual() {
+ assertThat(data1).recreatesEqual(SafetyCenterData.CREATOR)
+ assertThat(data2).recreatesEqual(SafetyCenterData.CREATOR)
+ }
+
+ @Test
+ fun equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
+ EqualsHashCodeToStringTester()
+ .addEqualityGroup(
+ data1,
+ SafetyCenterData(status1, listOf(issue1), listOf(entryOrGroup1),
+ listOf(staticEntryGroup1))
+ )
+ .addEqualityGroup(
+ data2,
+ SafetyCenterData(status2, listOf(issue2), listOf(entryOrGroup2),
+ listOf(staticEntryGroup2))
+ )
+ .addEqualityGroup(
+ SafetyCenterData(status1, listOf(), listOf(), listOf()),
+ SafetyCenterData(status1, listOf(), listOf(), listOf())
+ )
+ .addEqualityGroup(
+ SafetyCenterData(status2, listOf(issue1), listOf(entryOrGroup1),
+ listOf(staticEntryGroup1))
+ )
+ .addEqualityGroup(
+ SafetyCenterData(status1, listOf(issue2), listOf(entryOrGroup1),
+ listOf(staticEntryGroup1))
+ )
+ .addEqualityGroup(
+ SafetyCenterData(status1, listOf(issue1), listOf(entryOrGroup2),
+ listOf(staticEntryGroup1))
+ )
+ .addEqualityGroup(
+ SafetyCenterData(status1, listOf(issue1), listOf(entryOrGroup1),
+ listOf(staticEntryGroup2))
+ )
+ .test()
+ }
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryGroupTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryGroupTest.kt
index 74d3e5f62..404dde8dc 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryGroupTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryGroupTest.kt
@@ -20,49 +20,48 @@ import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
import android.safetycenter.SafetyCenterEntry
import android.safetycenter.SafetyCenterEntryGroup
+import android.safetycenter.cts.testing.EqualsHashCodeToStringTester
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.ext.truth.os.ParcelableSubject.assertThat
import androidx.test.filters.SdkSuppress
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
+import kotlin.test.assertFailsWith
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
class SafetyCenterEntryGroupTest {
private val context: Context = ApplicationProvider.getApplicationContext()
- private val pendingIntent = PendingIntent.getActivity(
- context,
- /* requestCode= */ 0,
- Intent("Fake Data"),
- PendingIntent.FLAG_IMMUTABLE)
+ private val pendingIntent =
+ PendingIntent.getActivity(context, 0, Intent("Fake Data"), PendingIntent.FLAG_IMMUTABLE)
- val entry1 = SafetyCenterEntry.Builder("eNtRy_iD_OnE")
- .setTitle("An entry title")
+ private val entry1 =
+ SafetyCenterEntry.Builder("eNtRy_iD_OnE", "An entry title")
.setPendingIntent(pendingIntent)
.setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
.build()
- val entry2 = SafetyCenterEntry.Builder("eNtRy_iD_TwO")
- .setTitle("Another entry title")
+ private val entry2 =
+ SafetyCenterEntry.Builder("eNtRy_iD_TwO", "Another entry title")
.setPendingIntent(pendingIntent)
.setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
.build()
- val groupId1 = "gRoUp_iD_oNe"
- val groupId2 = "gRoUp_iD_tWo"
+ private val groupId1 = "gRoUp_iD_oNe"
+ private val groupId2 = "gRoUp_iD_tWo"
- val entryGroup1 = SafetyCenterEntryGroup.Builder(groupId1)
- .setTitle("A group title")
+ private val entryGroup1 =
+ SafetyCenterEntryGroup.Builder(groupId1, "A group title")
.setSummary("A group summary")
.setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
.setEntries(listOf(entry1))
.build()
- val entryGroup2 = SafetyCenterEntryGroup.Builder(groupId2)
- .setTitle("Another group title")
+ private val entryGroup2 =
+ SafetyCenterEntryGroup.Builder(groupId2, "Another group title")
.setSummary("Another group summary")
.setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
.setEntries(listOf(entry2))
@@ -77,45 +76,51 @@ class SafetyCenterEntryGroupTest {
@Test
fun getTitle_returnsTitle() {
assertThat(SafetyCenterEntryGroup.Builder(entryGroup1).setTitle("title one").build().title)
- .isEqualTo("title one")
+ .isEqualTo("title one")
assertThat(SafetyCenterEntryGroup.Builder(entryGroup1).setTitle("title two").build().title)
- .isEqualTo("title two")
+ .isEqualTo("title two")
}
@Test
fun getSummary_returnsSummary() {
assertThat(SafetyCenterEntryGroup.Builder(entryGroup1).setSummary("one").build().summary)
- .isEqualTo("one")
+ .isEqualTo("one")
assertThat(SafetyCenterEntryGroup.Builder(entryGroup1).setSummary("two").build().summary)
- .isEqualTo("two")
+ .isEqualTo("two")
assertThat(SafetyCenterEntryGroup.Builder(entryGroup1).setSummary(null).build().summary)
- .isNull()
+ .isNull()
}
@Test
fun getSeverityLevel_returnsSeverityLevel() {
- assertThat(SafetyCenterEntryGroup.Builder(entryGroup1)
+ assertThat(
+ SafetyCenterEntryGroup.Builder(entryGroup1)
.setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
.build()
- .severityLevel)
- .isEqualTo(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
- assertThat(SafetyCenterEntryGroup.Builder(entryGroup1)
+ .severityLevel
+ )
+ .isEqualTo(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
+ assertThat(
+ SafetyCenterEntryGroup.Builder(entryGroup1)
.setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_UNSPECIFIED)
.build()
- .severityLevel)
- .isEqualTo(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_UNSPECIFIED)
+ .severityLevel
+ )
+ .isEqualTo(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_UNSPECIFIED)
}
@Test
fun getSeverityUnspecifiedIconType_returnsSeverityUnspecifiedIconType() {
assertThat(entryGroup1.severityUnspecifiedIconType)
- .isEqualTo(SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_NO_ICON)
- assertThat(SafetyCenterEntryGroup.Builder(entryGroup1)
+ .isEqualTo(SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_NO_ICON)
+ assertThat(
+ SafetyCenterEntryGroup.Builder(entryGroup1)
.setSeverityUnspecifiedIconType(
- SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_PRIVACY)
+ SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_PRIVACY)
.build()
- .severityUnspecifiedIconType)
- .isEqualTo(SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_PRIVACY)
+ .severityUnspecifiedIconType
+ )
+ .isEqualTo(SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_PRIVACY)
}
@Test
@@ -125,136 +130,60 @@ class SafetyCenterEntryGroupTest {
}
@Test
- fun getEntries_mutationsAreNotReflected() {
+ fun getEntries_mutationsAreNotAllowed() {
val mutatedEntries = entryGroup1.entries
- mutatedEntries.add(entry2)
- assertThat(mutatedEntries).containsExactly(entry1, entry2)
- assertThat(entryGroup1.entries).doesNotContain(entry2)
+ assertFailsWith(UnsupportedOperationException::class) { mutatedEntries.add(entry2) }
}
@Test
fun describeContents_returns0() {
assertThat(entryGroup1.describeContents()).isEqualTo(0)
- }
-
- @Test
- fun createFromParcel_withWriteToParcel_returnsEquivalentObject() {
- val parcel = Parcel.obtain()
-
- entryGroup1.writeToParcel(parcel, /* flags= */ 0)
- parcel.setDataPosition(0)
-
- val fromParcel = SafetyCenterEntryGroup.CREATOR.createFromParcel(parcel)
- parcel.recycle()
-
- assertThat(fromParcel).isEqualTo(entryGroup1)
- }
-
- @Test
- fun equals_hashCode_toString_equalByReference_areEqual() {
- assertThat(entryGroup1).isEqualTo(entryGroup1)
- assertThat(entryGroup1.hashCode()).isEqualTo(entryGroup1.hashCode())
- assertThat(entryGroup1.toString()).isEqualTo(entryGroup1.toString())
- }
-
- @Test
- fun equals_hashCode_toString_equalByValue_areEqual() {
- val entry = SafetyCenterEntryGroup.Builder(groupId1)
- .setTitle("A group title")
- .setSummary("A group summary")
- .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
- .setEntries(listOf(entry1))
- .build()
- val equivalentEntry = SafetyCenterEntryGroup.Builder(groupId1)
- .setTitle("A group title")
- .setSummary("A group summary")
- .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
- .setEntries(listOf(entry1))
- .build()
-
- assertThat(entry).isEqualTo(equivalentEntry)
- assertThat(entry.hashCode()).isEqualTo(equivalentEntry.hashCode())
- assertThat(entry.toString()).isEqualTo(equivalentEntry.toString())
- }
-
- @Test
- fun equals_hashCode_toString_fromCopyBuilder_areEqual() {
- val equivalentToEntryGroup1 = SafetyCenterEntryGroup.Builder(entryGroup1).build()
-
- assertThat(equivalentToEntryGroup1).isEqualTo(entryGroup1)
- assertThat(equivalentToEntryGroup1.hashCode()).isEqualTo(entryGroup1.hashCode())
- assertThat(equivalentToEntryGroup1.toString()).isEqualTo(entryGroup1.toString())
- }
-
- @Test
- fun equals_toString_withDifferentIds_areNotEqual() {
- val differentFromEntryGroup1 = SafetyCenterEntryGroup.Builder(entryGroup1)
- .setId("different!")
- .build()
-
- assertThat(differentFromEntryGroup1).isNotEqualTo(entryGroup1)
- assertThat(differentFromEntryGroup1.toString()).isNotEqualTo(entryGroup1.toString())
- }
-
- @Test
- fun equals_toString_withDifferentTitles_areNotEqual() {
- val differentFromEntryGroup1 = SafetyCenterEntryGroup.Builder(entryGroup1)
- .setTitle("different!")
- .build()
-
- assertThat(differentFromEntryGroup1).isNotEqualTo(entryGroup1)
- assertThat(differentFromEntryGroup1.toString()).isNotEqualTo(entryGroup1.toString())
- }
-
- @Test
- fun equals_toString_withDifferentSummaries_areNotEqual() {
- val differentFromEntryGroup1 = SafetyCenterEntryGroup.Builder(entryGroup1)
- .setSummary("different!")
- .build()
-
- assertThat(differentFromEntryGroup1).isNotEqualTo(entryGroup1)
- assertThat(differentFromEntryGroup1.toString()).isNotEqualTo(entryGroup1.toString())
- }
-
- @Test
- fun equals_toString_withDifferentSeverityLevels_areNotEqual() {
- val differentFromEntryGroup1 = SafetyCenterEntryGroup.Builder(entryGroup1)
- .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_UNKNOWN)
- .build()
-
- assertThat(differentFromEntryGroup1).isNotEqualTo(entryGroup1)
- assertThat(differentFromEntryGroup1.toString()).isNotEqualTo(entryGroup1.toString())
- }
-
- @Test
- fun equals_toString_withDifferentSeverityUnspecifiedIconTypes_areNotEqual() {
- val differentFromEntryGroup1 = SafetyCenterEntryGroup.Builder(entryGroup1)
- .setSeverityUnspecifiedIconType(
+ assertThat(entryGroup2.describeContents()).isEqualTo(0)
+ }
+
+ @Test
+ fun parcelRoundTrip_recreatesEqual() {
+ assertThat(entryGroup1).recreatesEqual(SafetyCenterEntryGroup.CREATOR)
+ assertThat(entryGroup2).recreatesEqual(SafetyCenterEntryGroup.CREATOR)
+ }
+
+ @Test
+ fun equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
+ EqualsHashCodeToStringTester()
+ .addEqualityGroup(
+ entryGroup1,
+ SafetyCenterEntryGroup.Builder(entryGroup1).build(),
+ SafetyCenterEntryGroup.Builder(groupId1, "A group title")
+ .setSummary("A group summary")
+ .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
+ .setEntries(listOf(entry1))
+ .build()
+ )
+ .addEqualityGroup(entryGroup2)
+ .addEqualityGroup(
+ SafetyCenterEntryGroup.Builder(entryGroup1).setId("different!").build())
+ .addEqualityGroup(
+ SafetyCenterEntryGroup.Builder(entryGroup1).setTitle("different!").build())
+ .addEqualityGroup(
+ SafetyCenterEntryGroup.Builder(entryGroup1).setSummary("different!").build()
+ )
+ .addEqualityGroup(
+ SafetyCenterEntryGroup.Builder(entryGroup1)
+ .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_UNKNOWN)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetyCenterEntryGroup.Builder(entryGroup1)
+ .setSeverityUnspecifiedIconType(
SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_PRIVACY)
- .build()
-
- assertThat(differentFromEntryGroup1).isNotEqualTo(entryGroup1)
- assertThat(differentFromEntryGroup1.toString()).isNotEqualTo(entryGroup1.toString())
- }
-
- @Test
- fun equals_toString_withDifferentEntries_areNotEqual() {
- val differentFromEntryGroup1 = SafetyCenterEntryGroup.Builder(entryGroup1)
- .setEntries(listOf(entry2))
- .build()
-
- assertThat(differentFromEntryGroup1).isNotEqualTo(entryGroup1)
- assertThat(differentFromEntryGroup1.toString()).isNotEqualTo(entryGroup1.toString())
- }
-
- @Test
- fun equals_toString_withDifferentEntries_emptyList_areNotEqual() {
- val differentFromEntryGroup1 = SafetyCenterEntryGroup.Builder(entryGroup1)
- .setEntries(listOf())
- .build()
-
- assertThat(differentFromEntryGroup1).isNotEqualTo(entryGroup1)
- assertThat(differentFromEntryGroup1.toString()).isNotEqualTo(entryGroup1.toString())
- }
-} \ No newline at end of file
+ .build()
+ )
+ .addEqualityGroup(
+ SafetyCenterEntryGroup.Builder(entryGroup1).setEntries(listOf(entry2)).build()
+ )
+ .addEqualityGroup(
+ SafetyCenterEntryGroup.Builder(entryGroup1).setEntries(emptyList()).build())
+ .test()
+ }
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryOrGroupTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryOrGroupTest.kt
index 193643bcf..dc14cc131 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryOrGroupTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryOrGroupTest.kt
@@ -20,12 +20,13 @@ import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
import android.safetycenter.SafetyCenterEntry
import android.safetycenter.SafetyCenterEntryGroup
import android.safetycenter.SafetyCenterEntryOrGroup
+import android.safetycenter.cts.testing.EqualsHashCodeToStringTester
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.ext.truth.os.ParcelableSubject.assertThat
import androidx.test.filters.SdkSuppress
import com.google.common.truth.Truth.assertThat
import org.junit.Test
@@ -36,38 +37,35 @@ import org.junit.runner.RunWith
class SafetyCenterEntryOrGroupTest {
private val context: Context = ApplicationProvider.getApplicationContext()
- private val pendingIntent = PendingIntent.getActivity(
- context,
- /* requestCode= */ 0,
- Intent("Fake Data"),
- PendingIntent.FLAG_IMMUTABLE)
+ private val pendingIntent =
+ PendingIntent.getActivity(context, 0, Intent("Fake Data"), PendingIntent.FLAG_IMMUTABLE)
- val entry1 = SafetyCenterEntry.Builder("eNtRy_iD_OnE")
- .setTitle("An entry title")
+ private val entry1 =
+ SafetyCenterEntry.Builder("eNtRy_iD_OnE", "An entry title")
.setPendingIntent(pendingIntent)
.setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
.build()
- val entry2 = SafetyCenterEntry.Builder("eNtRy_iD_TwO")
- .setTitle("Another entry title")
+ private val entry2 =
+ SafetyCenterEntry.Builder("eNtRy_iD_TwO", "Another entry title")
.setPendingIntent(pendingIntent)
.setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
.build()
- val entryGroup1 = SafetyCenterEntryGroup.Builder("gRoUp_iD_oNe")
- .setTitle("A group title")
+ private val entryGroup1 =
+ SafetyCenterEntryGroup.Builder("gRoUp_iD_oNe", "A group title")
.setSummary("A group summary")
.setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
.setEntries(listOf(entry1))
.build()
- val entryGroup2 = SafetyCenterEntryGroup.Builder("gRoUp_iD_tWo")
- .setTitle("Another group title")
+ private val entryGroup2 =
+ SafetyCenterEntryGroup.Builder("gRoUp_iD_tWo", "Another group title")
.setSummary("Another group summary")
.setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
.setEntries(listOf(entry2))
.build()
- val entryOrGroupWithEntry = SafetyCenterEntryOrGroup(entry1)
- val entryOrGroupWithGroup = SafetyCenterEntryOrGroup(entryGroup1)
+ private val entryOrGroupWithEntry = SafetyCenterEntryOrGroup(entry1)
+ private val entryOrGroupWithGroup = SafetyCenterEntryOrGroup(entryGroup1)
@Test
fun getEntry_returnsEntry() {
@@ -92,81 +90,22 @@ class SafetyCenterEntryOrGroupTest {
@Test
fun describeContents_returns0() {
assertThat(entryOrGroupWithEntry.describeContents()).isEqualTo(0)
+ assertThat(entryOrGroupWithGroup.describeContents()).isEqualTo(0)
}
@Test
- fun createFromParcel_withWriteToParcel_withEntry_returnsEquivalentObject() {
- runCreateFromParcel_withWriteToParcel_withGroup_returnsEquivalentObjectTest(
- entryOrGroupWithEntry)
+ fun parcelRoundTrip_recreatesEqual() {
+ assertThat(entryOrGroupWithEntry).recreatesEqual(SafetyCenterEntryOrGroup.CREATOR)
+ assertThat(entryOrGroupWithGroup).recreatesEqual(SafetyCenterEntryOrGroup.CREATOR)
}
@Test
- fun createFromParcel_withWriteToParcel_withGroup_returnsEquivalentObject() {
- runCreateFromParcel_withWriteToParcel_withGroup_returnsEquivalentObjectTest(
- entryOrGroupWithGroup)
+ fun equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
+ EqualsHashCodeToStringTester()
+ .addEqualityGroup(entryOrGroupWithEntry, SafetyCenterEntryOrGroup(entry1))
+ .addEqualityGroup(entryOrGroupWithGroup, SafetyCenterEntryOrGroup(entryGroup1))
+ .addEqualityGroup(SafetyCenterEntryOrGroup(entry2))
+ .addEqualityGroup(SafetyCenterEntryOrGroup(entryGroup2))
+ .test()
}
-
- fun runCreateFromParcel_withWriteToParcel_withGroup_returnsEquivalentObjectTest(
- entryOrGroup: SafetyCenterEntryOrGroup
- ) {
- val parcel: Parcel = Parcel.obtain()
-
- entryOrGroup.writeToParcel(parcel, 0 /* flags */)
- parcel.setDataPosition(0)
- val fromParcel = SafetyCenterEntryOrGroup.CREATOR.createFromParcel(parcel)
- parcel.recycle()
-
- assertThat(fromParcel).isEqualTo(entryOrGroup)
- }
-
- @Test
- fun equals_hashCode_toString_whenEqualByReference_areEqual() {
- assertThat(entryOrGroupWithEntry).isEqualTo(entryOrGroupWithEntry)
- assertThat(entryOrGroupWithEntry.hashCode()).isEqualTo(entryOrGroupWithEntry.hashCode())
- assertThat(entryOrGroupWithEntry.toString()).isEqualTo(entryOrGroupWithEntry.toString())
- }
-
- @Test
- fun equals_hashCode_toString_whenEqualByValue_withEntry_areEqual() {
- val entryOrGroup = SafetyCenterEntryOrGroup(entry1)
- val equivalentEntryOrGroup = SafetyCenterEntryOrGroup(entry1)
-
- assertThat(entryOrGroup).isEqualTo(equivalentEntryOrGroup)
- assertThat(entryOrGroup.hashCode()).isEqualTo(equivalentEntryOrGroup.hashCode())
- assertThat(entryOrGroup.toString()).isEqualTo(equivalentEntryOrGroup.toString())
- }
-
- @Test
- fun equals_hashCode_toString_whenEqualByValue_withGroup_areEqual() {
- val entryOrGroup = SafetyCenterEntryOrGroup(entryGroup1)
- val equivalentEntryOrGroup = SafetyCenterEntryOrGroup(entryGroup1)
-
- assertThat(entryOrGroup).isEqualTo(equivalentEntryOrGroup)
- assertThat(entryOrGroup.hashCode()).isEqualTo(equivalentEntryOrGroup.hashCode())
- assertThat(entryOrGroup.toString()).isEqualTo(equivalentEntryOrGroup.toString())
- }
-
- @Test
- fun equals_toString_withDifferentEntryAndGroup_areNotEqual() {
- assertThat(entryOrGroupWithEntry).isNotEqualTo(entryOrGroupWithGroup)
- assertThat(entryOrGroupWithEntry.toString()).isNotEqualTo(entryOrGroupWithGroup.toString())
- }
-
- @Test
- fun equals_toString_withDifferentEntries_areNotEqual() {
- val entryOrGroup = SafetyCenterEntryOrGroup(entry1)
- val differentEntryOrGroup = SafetyCenterEntryOrGroup(entry2)
-
- assertThat(entryOrGroup).isNotEqualTo(differentEntryOrGroup)
- assertThat(entryOrGroup.toString()).isNotEqualTo(differentEntryOrGroup.toString())
- }
-
- @Test
- fun equals_toString_withDifferentGroups_areNotEqual() {
- val entryOrGroup = SafetyCenterEntryOrGroup(entryGroup1)
- val differentEntryOrGroup = SafetyCenterEntryOrGroup(entryGroup2)
-
- assertThat(entryOrGroup).isNotEqualTo(differentEntryOrGroup)
- assertThat(entryOrGroup.toString()).isNotEqualTo(differentEntryOrGroup.toString())
- }
-} \ No newline at end of file
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryTest.kt
index 423815cb6..1e435c4ce 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryTest.kt
@@ -20,10 +20,11 @@ import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
import android.safetycenter.SafetyCenterEntry
+import android.safetycenter.cts.testing.EqualsHashCodeToStringTester
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.ext.truth.os.ParcelableSubject.assertThat
import androidx.test.filters.SdkSuppress
import com.google.common.truth.Truth.assertThat
import org.junit.Test
@@ -34,24 +35,25 @@ import org.junit.runner.RunWith
class SafetyCenterEntryTest {
private val context: Context = ApplicationProvider.getApplicationContext()
- private val pendingIntent1 = PendingIntent.getActivity(
+ private val pendingIntent1 =
+ PendingIntent.getActivity(context, 0, Intent("Fake Data"), PendingIntent.FLAG_IMMUTABLE)
+ private val pendingIntent2 =
+ PendingIntent.getActivity(
context,
- /* requestCode= */ 0,
- Intent("Fake Data"),
- PendingIntent.FLAG_IMMUTABLE)
- private val pendingIntent2 = PendingIntent.getActivity(
- context,
- /* requestCode= */ 0,
+ 0,
Intent("Fake Different Data"),
- PendingIntent.FLAG_IMMUTABLE)
-
- private val iconAction1 = SafetyCenterEntry.IconAction(
- SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR, pendingIntent1)
- private val iconAction2 = SafetyCenterEntry.IconAction(
- SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_INFO, pendingIntent2)
-
- private val entry1 = SafetyCenterEntry.Builder("eNtRy_iD")
- .setTitle("a title")
+ PendingIntent.FLAG_IMMUTABLE
+ )
+
+ private val iconAction1 =
+ SafetyCenterEntry.IconAction(SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR,
+ pendingIntent1)
+ private val iconAction2 =
+ SafetyCenterEntry.IconAction(SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_INFO,
+ pendingIntent2)
+
+ private val entry1 =
+ SafetyCenterEntry.Builder("eNtRy_iD", "a title")
.setSummary("a summary")
.setPendingIntent(pendingIntent1)
.setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_UNKNOWN)
@@ -60,97 +62,99 @@ class SafetyCenterEntryTest {
@Test
fun getId_returnsId() {
- assertThat(SafetyCenterEntry.Builder(entry1).setId("id_one").build().id)
- .isEqualTo("id_one")
- assertThat(SafetyCenterEntry.Builder(entry1).setId("id_two").build().id)
- .isEqualTo("id_two")
+ assertThat(SafetyCenterEntry.Builder(entry1).setId("id_one").build().id).isEqualTo("id_one")
+ assertThat(SafetyCenterEntry.Builder(entry1).setId("id_two").build().id).isEqualTo("id_two")
}
@Test
fun getTitle_returnsTitle() {
assertThat(SafetyCenterEntry.Builder(entry1).setTitle("a title").build().title)
- .isEqualTo("a title")
+ .isEqualTo("a title")
assertThat(SafetyCenterEntry.Builder(entry1).setTitle("another title").build().title)
- .isEqualTo("another title")
+ .isEqualTo("another title")
}
@Test
fun getSummary_returnsSummary() {
assertThat(SafetyCenterEntry.Builder(entry1).setSummary("a summary").build().summary)
- .isEqualTo("a summary")
+ .isEqualTo("a summary")
assertThat(SafetyCenterEntry.Builder(entry1).setSummary("another summary").build().summary)
- .isEqualTo("another summary")
- assertThat(SafetyCenterEntry.Builder(entry1).setSummary(null).build().summary)
- .isNull()
+ .isEqualTo("another summary")
+ assertThat(SafetyCenterEntry.Builder(entry1).setSummary(null).build().summary).isNull()
}
@Test
fun getSeverityLevel_returnsSeverityLevel() {
- assertThat(SafetyCenterEntry.Builder(entry1)
+ assertThat(
+ SafetyCenterEntry.Builder(entry1)
.setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
.build()
- .severityLevel)
- .isEqualTo(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
- assertThat(SafetyCenterEntry.Builder(entry1)
+ .severityLevel
+ )
+ .isEqualTo(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
+ assertThat(
+ SafetyCenterEntry.Builder(entry1)
.setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
.build()
- .severityLevel)
- .isEqualTo(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
+ .severityLevel
+ )
+ .isEqualTo(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
}
@Test
fun getSeverityUnspecifiedIconType_returnsSeverityUnspecifiedIconType() {
- assertThat(entry1.severityUnspecifiedIconType).isEqualTo(
- SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_NO_ICON)
- assertThat(SafetyCenterEntry.Builder(entry1)
+ assertThat(entry1.severityUnspecifiedIconType)
+ .isEqualTo(SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_NO_ICON)
+ assertThat(
+ SafetyCenterEntry.Builder(entry1)
.setSeverityUnspecifiedIconType(
- SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_PRIVACY)
+ SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_PRIVACY)
.build()
- .severityUnspecifiedIconType)
- .isEqualTo(SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_PRIVACY)
+ .severityUnspecifiedIconType
+ )
+ .isEqualTo(SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_PRIVACY)
}
@Test
fun isEnabled_returnsIsEnabled() {
- assertThat(SafetyCenterEntry.Builder(entry1).setEnabled(true).build().isEnabled)
- .isTrue()
- assertThat(SafetyCenterEntry.Builder(entry1).setEnabled(false).build().isEnabled)
- .isFalse()
+ assertThat(SafetyCenterEntry.Builder(entry1).setEnabled(true).build().isEnabled).isTrue()
+ assertThat(SafetyCenterEntry.Builder(entry1).setEnabled(false).build().isEnabled).isFalse()
}
@Test
fun isEnabled_defaultTrue() {
- assertThat(SafetyCenterEntry.Builder("eNtRy_iD")
- .setTitle("a title")
+ assertThat(
+ SafetyCenterEntry.Builder("eNtRy_iD", "a title")
.setPendingIntent(pendingIntent1)
.setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_UNKNOWN)
.build()
- .isEnabled)
- .isTrue()
+ .isEnabled
+ )
+ .isTrue()
}
@Test
fun getPendingIntent_returnsPendingIntent() {
- assertThat(SafetyCenterEntry.Builder(entry1)
- .setPendingIntent(pendingIntent1)
- .build()
- .pendingIntent)
- .isEqualTo(pendingIntent1)
- assertThat(SafetyCenterEntry.Builder(entry1)
- .setPendingIntent(pendingIntent2)
- .build()
- .pendingIntent)
- .isEqualTo(pendingIntent2)
+ assertThat(
+ SafetyCenterEntry.Builder(entry1).setPendingIntent(pendingIntent1).build().pendingIntent
+ )
+ .isEqualTo(pendingIntent1)
+ assertThat(
+ SafetyCenterEntry.Builder(entry1).setPendingIntent(pendingIntent2).build().pendingIntent
+ )
+ .isEqualTo(pendingIntent2)
+ assertThat(SafetyCenterEntry.Builder(entry1).setPendingIntent(null).build().pendingIntent)
+ .isNull()
}
@Test
fun getIconAction_returnsIconAction() {
assertThat(SafetyCenterEntry.Builder(entry1).setIconAction(iconAction1).build().iconAction)
- .isEqualTo(iconAction1)
+ .isEqualTo(iconAction1)
assertThat(SafetyCenterEntry.Builder(entry1).setIconAction(iconAction2).build().iconAction)
- .isEqualTo(iconAction2)
- assertThat(SafetyCenterEntry.Builder(entry1).setIconAction(null).build().iconAction)
- .isNull()
+ .isEqualTo(iconAction2)
+ assertThat(
+ SafetyCenterEntry.Builder(entry1).setIconAction(null).build().iconAction).isNull()
}
@Test
@@ -159,163 +163,103 @@ class SafetyCenterEntryTest {
}
@Test
- fun createFromParcel_withWriteToParcel_returnsEquivalentObject() {
- val parcel = Parcel.obtain()
-
- entry1.writeToParcel(parcel, /* flags= */ 0)
- parcel.setDataPosition(0)
-
- val fromParcel = SafetyCenterEntry.CREATOR.createFromParcel(parcel)
- parcel.recycle()
-
- assertThat(fromParcel).isEqualTo(entry1)
- }
-
- @Test
- fun equals_hashCode_toString_equalByReference_areEqual() {
- assertThat(entry1).isEqualTo(entry1)
- assertThat(entry1.hashCode()).isEqualTo(entry1.hashCode())
- assertThat(entry1.toString()).isEqualTo(entry1.toString())
+ fun parcelRoundTrip_recreatesEqual() {
+ assertThat(entry1).recreatesEqual(SafetyCenterEntry.CREATOR)
+ assertThat(
+ SafetyCenterEntry.Builder(entry1)
+ .setSummary(null)
+ .setPendingIntent(null)
+ .setIconAction(null)
+ .build()
+ )
+ .recreatesEqual(SafetyCenterEntry.CREATOR)
}
@Test
- fun equals_hashCode_toString_equalByValue_areEqual() {
- val entry = SafetyCenterEntry.Builder("id")
- .setTitle("a title")
- .setSummary("a summary")
- .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
- .setSeverityUnspecifiedIconType(
+ fun equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
+ EqualsHashCodeToStringTester()
+ .addEqualityGroup(entry1, SafetyCenterEntry.Builder(entry1).build())
+ .addEqualityGroup(
+ SafetyCenterEntry.Builder("id", "a title")
+ .setSummary("a summary")
+ .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
+ .setSeverityUnspecifiedIconType(
SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_PRIVACY)
- .setPendingIntent(pendingIntent1)
- .setIconAction(SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_INFO, pendingIntent2)
- .build()
- val equivalentEntry = SafetyCenterEntry.Builder("id")
- .setTitle("a title")
- .setSummary("a summary")
- .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
- .setSeverityUnspecifiedIconType(
+ .setPendingIntent(pendingIntent1)
+ .setIconAction(SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_INFO,
+ pendingIntent2)
+ .build(),
+ SafetyCenterEntry.Builder("id", "a title")
+ .setSummary("a summary")
+ .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
+ .setSeverityUnspecifiedIconType(
SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_PRIVACY)
- .setPendingIntent(pendingIntent1)
- .setIconAction(SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_INFO, pendingIntent2)
- .build()
-
- assertThat(entry).isEqualTo(equivalentEntry)
- assertThat(entry.hashCode()).isEqualTo(equivalentEntry.hashCode())
- assertThat(entry.toString()).isEqualTo(equivalentEntry.toString())
- }
-
- @Test
- fun equals_hashCode_toString_fromCopyBuilder_areEqual() {
- val copyOfEntry1 = SafetyCenterEntry.Builder(entry1).build()
-
- assertThat(copyOfEntry1).isEqualTo(entry1)
- assertThat(copyOfEntry1.hashCode()).isEqualTo(entry1.hashCode())
- assertThat(copyOfEntry1.toString()).isEqualTo(entry1.toString())
- }
-
- @Test
- fun equals_toString_withDifferentIds_areNotEqual() {
- val differentFromEntry1 = SafetyCenterEntry.Builder(entry1)
- .setId("a different id")
- .build()
-
- assertThat(differentFromEntry1).isNotEqualTo(entry1)
- assertThat(differentFromEntry1.toString()).isNotEqualTo(entry1.toString())
- }
-
- @Test
- fun equals_toString_withDifferentTitles_areNotEqual() {
- val differentFromEntry1 = SafetyCenterEntry.Builder(entry1)
- .setTitle("a different title")
- .build()
-
- assertThat(differentFromEntry1).isNotEqualTo(entry1)
- assertThat(differentFromEntry1.toString()).isNotEqualTo(entry1.toString())
- }
-
- @Test
- fun equals_toString_withDifferentSummaries_areNotEqual() {
- val differentFromEntry1 = SafetyCenterEntry.Builder(entry1)
- .setSummary("a different summary")
- .build()
-
- assertThat(differentFromEntry1).isNotEqualTo(entry1)
- assertThat(differentFromEntry1.toString()).isNotEqualTo(entry1.toString())
- }
-
- @Test
- fun equals_toString_withDifferentSeverityLevels_areNotEqual() {
- val differentFromEntry1 = SafetyCenterEntry.Builder(entry1)
- .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_CRITICAL_WARNING)
- .build()
-
- assertThat(differentFromEntry1).isNotEqualTo(entry1)
- assertThat(differentFromEntry1.toString()).isNotEqualTo(entry1.toString())
- }
-
- @Test
- fun equals_toString_withDifferentSeverityUnspecifiedIconTypes_areNotEqual() {
- val differentFromEntry1 = SafetyCenterEntry.Builder(entry1)
- .setSeverityUnspecifiedIconType(
+ .setPendingIntent(pendingIntent1)
+ .setIconAction(SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_INFO,
+ pendingIntent2)
+ .build()
+ )
+ .addEqualityGroup(SafetyCenterEntry.Builder(entry1).setId("a different id").build())
+ .addEqualityGroup(
+ SafetyCenterEntry.Builder(entry1).setTitle("a different title").build())
+ .addEqualityGroup(
+ SafetyCenterEntry.Builder(entry1).setSummary("a different summary").build())
+ .addEqualityGroup(
+ SafetyCenterEntry.Builder(entry1)
+ .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_CRITICAL_WARNING)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetyCenterEntry.Builder(entry1)
+ .setSeverityUnspecifiedIconType(
SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_PRIVACY)
- .build()
-
- assertThat(differentFromEntry1).isNotEqualTo(entry1)
- assertThat(differentFromEntry1.toString()).isNotEqualTo(entry1.toString())
- }
-
- @Test
- fun equals_toString_withDifferentEnabledValues_areNotEqual() {
- val differentFromEntry1 = SafetyCenterEntry.Builder(entry1)
- .setEnabled(false)
- .build()
-
- assertThat(differentFromEntry1).isNotEqualTo(entry1)
- assertThat(differentFromEntry1.toString()).isNotEqualTo(entry1.toString())
- }
-
- @Test
- fun equals_toString_withDifferentPendingIntents_areNotEqual() {
- val differentFromEntry1 = SafetyCenterEntry.Builder(entry1)
- .setPendingIntent(pendingIntent2)
- .build()
-
- assertThat(differentFromEntry1).isNotEqualTo(entry1)
- assertThat(differentFromEntry1.toString()).isNotEqualTo(entry1.toString())
- }
-
- @Test
- fun equals_toString_withDifferentIconActions_areNotEqual() {
- val differentFromEntry1 = SafetyCenterEntry.Builder(entry1)
- .setIconAction(iconAction2)
- .build()
-
- assertThat(differentFromEntry1).isNotEqualTo(entry1)
- assertThat(differentFromEntry1.toString()).isNotEqualTo(entry1.toString())
+ .build()
+ )
+ .addEqualityGroup(SafetyCenterEntry.Builder(entry1).setEnabled(false).build())
+ .addEqualityGroup(
+ SafetyCenterEntry.Builder(entry1).setPendingIntent(pendingIntent2).build())
+ .addEqualityGroup(SafetyCenterEntry.Builder(entry1).setIconAction(iconAction2).build())
+ .test()
}
@Test
fun iconAction_getType_returnsType() {
- assertThat(SafetyCenterEntry.IconAction(
- SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR, pendingIntent1)
- .type)
- .isEqualTo(SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR)
- assertThat(SafetyCenterEntry.IconAction(
- SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_INFO, pendingIntent1)
- .type)
- .isEqualTo(SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_INFO)
+ assertThat(
+ SafetyCenterEntry.IconAction(
+ SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR,
+ pendingIntent1
+ )
+ .type
+ )
+ .isEqualTo(SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR)
+ assertThat(
+ SafetyCenterEntry.IconAction(
+ SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_INFO,
+ pendingIntent1
+ )
+ .type
+ )
+ .isEqualTo(SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_INFO)
}
@Test
fun iconAction_getPendingIntent_returnsPendingIntent() {
- assertThat(SafetyCenterEntry.IconAction(
- SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR, pendingIntent1)
- .pendingIntent)
- .isEqualTo(pendingIntent1)
- assertThat(SafetyCenterEntry.IconAction(
- SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR, pendingIntent2)
- .pendingIntent)
- .isEqualTo(pendingIntent2)
+ assertThat(
+ SafetyCenterEntry.IconAction(
+ SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR,
+ pendingIntent1
+ )
+ .pendingIntent
+ )
+ .isEqualTo(pendingIntent1)
+ assertThat(
+ SafetyCenterEntry.IconAction(
+ SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR,
+ pendingIntent2
+ )
+ .pendingIntent
+ )
+ .isEqualTo(pendingIntent2)
}
@Test
@@ -324,56 +268,39 @@ class SafetyCenterEntryTest {
}
@Test
- fun iconAction_createFromParcel_withWriteToParcel_returnsEquivalentObject() {
- val parcel = Parcel.obtain()
-
- iconAction1.writeToParcel(parcel, /* flags= */ 0)
- parcel.setDataPosition(0)
-
- val fromParcel = SafetyCenterEntry.IconAction.CREATOR.createFromParcel(parcel)
- parcel.recycle()
-
- assertThat(fromParcel).isEqualTo(iconAction1)
- }
-
- @Test
- fun iconAction_equals_hashCode_toString_equalByReference_areEqual() {
- assertThat(iconAction1).isEqualTo(iconAction1)
- assertThat(iconAction1.hashCode()).isEqualTo(iconAction1.hashCode())
- assertThat(iconAction1.toString()).isEqualTo(iconAction1.toString())
- }
-
- @Test
- fun iconAction_equals_hashCode_toString_equalByValue_areEqual() {
- val iconAction = SafetyCenterEntry.IconAction(
- SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR, pendingIntent1)
- val equivalentIconAction = SafetyCenterEntry.IconAction(
- SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR, pendingIntent1)
-
- assertThat(iconAction).isEqualTo(equivalentIconAction)
- assertThat(iconAction.hashCode()).isEqualTo(equivalentIconAction.hashCode())
- assertThat(iconAction.toString()).isEqualTo(equivalentIconAction.toString())
- }
-
- @Test
- fun iconAction_equals_toString_differentTypes_areNotEqual() {
- val iconAction = SafetyCenterEntry.IconAction(
- SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR, pendingIntent1)
- val differentIconAction = SafetyCenterEntry.IconAction(
- SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_INFO, pendingIntent1)
-
- assertThat(iconAction).isNotEqualTo(differentIconAction)
- assertThat(iconAction.toString()).isNotEqualTo(differentIconAction.toString())
+ fun iconAction_parcelRoundTrip_recreatesEqual() {
+ assertThat(iconAction1).recreatesEqual(SafetyCenterEntry.IconAction.CREATOR)
}
@Test
- fun intentAction_equals_toString_differentPendingIntents_areNotEqual() {
- val iconAction = SafetyCenterEntry.IconAction(
- SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR, pendingIntent1)
- val differentIconAction = SafetyCenterEntry.IconAction(
- SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR, pendingIntent2)
-
- assertThat(iconAction).isNotEqualTo(differentIconAction)
- assertThat(iconAction.toString()).isNotEqualTo(differentIconAction.toString())
+ fun iconAction_equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
+ EqualsHashCodeToStringTester()
+ .addEqualityGroup(
+ iconAction1,
+ SafetyCenterEntry.IconAction(
+ SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR,
+ pendingIntent1
+ )
+ )
+ .addEqualityGroup(
+ iconAction2,
+ SafetyCenterEntry.IconAction(
+ SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_INFO,
+ pendingIntent2
+ )
+ )
+ .addEqualityGroup(
+ SafetyCenterEntry.IconAction(
+ SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_INFO,
+ pendingIntent1
+ )
+ )
+ .addEqualityGroup(
+ SafetyCenterEntry.IconAction(
+ SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR,
+ pendingIntent2
+ )
+ )
+ .test()
}
-} \ No newline at end of file
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterErrorDetailsTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterErrorDetailsTest.kt
index e3e5d9c6c..86b6625ed 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterErrorDetailsTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterErrorDetailsTest.kt
@@ -17,9 +17,10 @@
package android.safetycenter.cts
import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
import android.safetycenter.SafetyCenterErrorDetails
+import android.safetycenter.cts.testing.EqualsHashCodeToStringTester
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.ext.truth.os.ParcelableSubject.assertThat
import androidx.test.filters.SdkSuppress
import com.google.common.truth.Truth.assertThat
import org.junit.Test
@@ -29,8 +30,8 @@ import org.junit.runner.RunWith
@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
class SafetyCenterErrorDetailsTest {
- val errorDetails1 = SafetyCenterErrorDetails("an error message")
- val errorDetails2 = SafetyCenterErrorDetails("another error message")
+ private val errorDetails1 = SafetyCenterErrorDetails("an error message")
+ private val errorDetails2 = SafetyCenterErrorDetails("another error message")
@Test
fun getErrorMessage_returnsErrorMessage() {
@@ -41,44 +42,24 @@ class SafetyCenterErrorDetailsTest {
@Test
fun describeContents_returns0() {
assertThat(errorDetails1.describeContents()).isEqualTo(0)
+ assertThat(errorDetails2.describeContents()).isEqualTo(0)
}
@Test
- fun createFromParcel_withWriteToParcel_returnsEquivalentObject() {
- val parcel = Parcel.obtain()
-
- errorDetails1.writeToParcel(parcel, /* flags= */ 0)
- parcel.setDataPosition(0)
-
- val fromParcel = SafetyCenterErrorDetails.CREATOR.createFromParcel(parcel)
- parcel.recycle()
-
- assertThat(fromParcel).isEqualTo(errorDetails1)
- }
-
- @Test
- fun equals_hashCode_toString_equalByReference_areEqual() {
- assertThat(errorDetails1).isEqualTo(errorDetails1)
- assertThat(errorDetails1.hashCode()).isEqualTo(errorDetails1.hashCode())
- assertThat(errorDetails1.toString()).isEqualTo(errorDetails1.toString())
+ fun parcelRoundTrip_recreatesEqual() {
+ assertThat(errorDetails1).recreatesEqual(SafetyCenterErrorDetails.CREATOR)
+ assertThat(errorDetails2).recreatesEqual(SafetyCenterErrorDetails.CREATOR)
}
@Test
- fun equals_hashCode_toString_equalByValue_areEqual() {
- val errorDetails = SafetyCenterErrorDetails("an error message")
- val equivalentErrorDetails = SafetyCenterErrorDetails("an error message")
-
- assertThat(errorDetails).isEqualTo(equivalentErrorDetails)
- assertThat(errorDetails.hashCode()).isEqualTo(equivalentErrorDetails.hashCode())
- assertThat(errorDetails.toString()).isEqualTo(equivalentErrorDetails.toString())
- }
-
- @Test
- fun equals_toString_withDifferentErrorMessages_areNotEqual() {
- val errorDetails = SafetyCenterErrorDetails("an error message")
- val differentErrorDetails = SafetyCenterErrorDetails("a different error message")
-
- assertThat(errorDetails).isNotEqualTo(differentErrorDetails)
- assertThat(errorDetails.toString()).isNotEqualTo(differentErrorDetails.toString())
+ fun equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
+ EqualsHashCodeToStringTester()
+ .addEqualityGroup(errorDetails1, SafetyCenterErrorDetails("an error message"))
+ .addEqualityGroup(errorDetails2, SafetyCenterErrorDetails("another error message"))
+ .addEqualityGroup(
+ SafetyCenterErrorDetails("a different error message"),
+ SafetyCenterErrorDetails("a different error message")
+ )
+ .test()
}
-} \ No newline at end of file
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterIssueTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterIssueTest.kt
index 819124611..33c5cf34e 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterIssueTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterIssueTest.kt
@@ -20,114 +20,114 @@ import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
import android.safetycenter.SafetyCenterIssue
+import android.safetycenter.cts.testing.EqualsHashCodeToStringTester
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.ext.truth.os.ParcelableSubject.assertThat
import androidx.test.filters.SdkSuppress
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
+import kotlin.test.assertFailsWith
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
class SafetyCenterIssueTest {
private val context: Context = ApplicationProvider.getApplicationContext()
- private val pendingIntent1 = PendingIntent.getActivity(
+ private val pendingIntent1 =
+ PendingIntent.getActivity(context, 0, Intent("Fake Data"), PendingIntent.FLAG_IMMUTABLE)
+ private val pendingIntent2 =
+ PendingIntent.getActivity(
context,
- /* requestCode= */ 0,
- Intent("Fake Data"),
- PendingIntent.FLAG_IMMUTABLE)
- private val pendingIntent2 = PendingIntent.getActivity(
- context,
- /* requestCode= */ 0,
+ 0,
Intent("Fake Different Data"),
- PendingIntent.FLAG_IMMUTABLE)
+ PendingIntent.FLAG_IMMUTABLE
+ )
- val action1 = SafetyCenterIssue.Action.Builder("action_id_1")
- .setLabel("an action")
- .setPendingIntent(pendingIntent1)
+ private val action1 =
+ SafetyCenterIssue.Action.Builder("action_id_1", "an action", pendingIntent1)
.setWillResolve(true)
.setIsInFlight(true)
.setSuccessMessage("a success message")
.build()
- val action2 = SafetyCenterIssue.Action.Builder("action_id_2")
- .setLabel("another action")
- .setPendingIntent(pendingIntent2)
+ private val action2 =
+ SafetyCenterIssue.Action.Builder("action_id_2", "another action", pendingIntent2)
.setWillResolve(false)
.setIsInFlight(false)
.build()
- val issue1 = SafetyCenterIssue.Builder("issue_id")
- .setTitle("Everything's good")
+ private val issue1 =
+ SafetyCenterIssue.Builder("issue_id", "Everything's good", "Please acknowledge this")
.setSubtitle("In the neighborhood")
- .setSummary("Please acknowledge this")
.setSeverityLevel(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_OK)
.setDismissible(true)
.setShouldConfirmDismissal(true)
.setActions(listOf(action1))
.build()
- val issueWithRequiredFieldsOnly = SafetyCenterIssue.Builder("issue_id")
- .setTitle("Everything's good")
- .setSummary("Please acknowledge this")
+ private val issueWithRequiredFieldsOnly =
+ SafetyCenterIssue.Builder("issue_id", "Everything's good", "Please acknowledge this")
.setSeverityLevel(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_OK)
.build()
@Test
fun getId_returnsId() {
- assertThat(SafetyCenterIssue.Builder(issue1).setId("an id").build().id)
- .isEqualTo("an id")
+ assertThat(SafetyCenterIssue.Builder(issue1).setId("an id").build().id).isEqualTo("an id")
assertThat(SafetyCenterIssue.Builder(issue1).setId("another id").build().id)
- .isEqualTo("another id")
+ .isEqualTo("another id")
}
@Test
fun getTitle_returnsTitle() {
assertThat(SafetyCenterIssue.Builder(issue1).setTitle("a title").build().title)
- .isEqualTo("a title")
+ .isEqualTo("a title")
assertThat(SafetyCenterIssue.Builder(issue1).setTitle("another title").build().title)
- .isEqualTo("another title")
+ .isEqualTo("another title")
}
@Test
fun getSubtitle_returnsSubtitle() {
assertThat(SafetyCenterIssue.Builder(issue1).setSubtitle("a subtitle").build().subtitle)
- .isEqualTo("a subtitle")
+ .isEqualTo("a subtitle")
assertThat(
- SafetyCenterIssue.Builder(issue1).setSubtitle("another subtitle").build().subtitle)
- .isEqualTo("another subtitle")
+ SafetyCenterIssue.Builder(issue1).setSubtitle("another subtitle").build().subtitle)
+ .isEqualTo("another subtitle")
}
@Test
fun getSummary_returnsSummary() {
assertThat(SafetyCenterIssue.Builder(issue1).setSummary("a summary").build().summary)
- .isEqualTo("a summary")
+ .isEqualTo("a summary")
assertThat(SafetyCenterIssue.Builder(issue1).setSummary("another summary").build().summary)
- .isEqualTo("another summary")
+ .isEqualTo("another summary")
}
@Test
fun getSeverityLevel_returnsSeverityLevel() {
- assertThat(SafetyCenterIssue.Builder(issue1)
+ assertThat(
+ SafetyCenterIssue.Builder(issue1)
.setSeverityLevel(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_RECOMMENDATION)
.build()
- .severityLevel)
- .isEqualTo(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_RECOMMENDATION)
- assertThat(SafetyCenterIssue.Builder(issue1)
+ .severityLevel
+ )
+ .isEqualTo(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_RECOMMENDATION)
+ assertThat(
+ SafetyCenterIssue.Builder(issue1)
.setSeverityLevel(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_CRITICAL_WARNING)
.build()
- .severityLevel)
- .isEqualTo(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_CRITICAL_WARNING)
+ .severityLevel
+ )
+ .isEqualTo(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_CRITICAL_WARNING)
}
@Test
fun isDismissible_returnsIsDismissible() {
assertThat(SafetyCenterIssue.Builder(issue1).setDismissible(true).build().isDismissible)
- .isTrue()
+ .isTrue()
assertThat(SafetyCenterIssue.Builder(issue1).setDismissible(false).build().isDismissible)
- .isFalse()
+ .isFalse()
}
@Test
@@ -137,16 +137,20 @@ class SafetyCenterIssueTest {
@Test
fun shouldConfirmDismissal_returnsShouldConfirmDismissal() {
- assertThat(SafetyCenterIssue.Builder(issue1)
+ assertThat(
+ SafetyCenterIssue.Builder(issue1)
.setShouldConfirmDismissal(true)
.build()
- .shouldConfirmDismissal())
- .isTrue()
- assertThat(SafetyCenterIssue.Builder(issue1)
+ .shouldConfirmDismissal()
+ )
+ .isTrue()
+ assertThat(
+ SafetyCenterIssue.Builder(issue1)
.setShouldConfirmDismissal(false)
.build()
- .shouldConfirmDismissal())
- .isFalse()
+ .shouldConfirmDismissal()
+ )
+ .isFalse()
}
@Test
@@ -156,159 +160,70 @@ class SafetyCenterIssueTest {
@Test
fun getActions_returnsActions() {
- assertThat(SafetyCenterIssue.Builder(issue1)
- .setActions(listOf(action1, action2))
- .build().actions)
- .containsExactly(action1, action2)
+ assertThat(
+ SafetyCenterIssue.Builder(issue1).setActions(listOf(action1, action2)).build().actions
+ )
+ .containsExactly(action1, action2)
+ .inOrder()
assertThat(SafetyCenterIssue.Builder(issue1).setActions(listOf(action2)).build().actions)
- .containsExactly(action2)
- assertThat(SafetyCenterIssue.Builder(issue1).setActions(listOf()).build().actions)
- .isEmpty()
+ .containsExactly(action2)
+ assertThat(SafetyCenterIssue.Builder(issue1).setActions(listOf()).build().actions).isEmpty()
}
@Test
- fun getActions_mutationsAreNotReflected() {
+ fun getActions_mutationsAreNotAllowed() {
val mutatedActions = issue1.actions
- mutatedActions.add(action2)
- assertThat(mutatedActions).containsExactly(action1, action2)
- assertThat(issue1.actions).doesNotContain(action2)
+ assertFailsWith(UnsupportedOperationException::class) { mutatedActions.add(action2) }
}
@Test
fun describeContents_returns0() {
assertThat(issue1.describeContents()).isEqualTo(0)
- }
-
- @Test
- fun createFromParcel_withWriteToParcel_returnsEquivalentObject() {
- val parcel = Parcel.obtain()
-
- issue1.writeToParcel(parcel, /* flags= */ 0)
- parcel.setDataPosition(0)
-
- val fromParcel = SafetyCenterIssue.CREATOR.createFromParcel(parcel)
- parcel.recycle()
-
- assertThat(fromParcel).isEqualTo(issue1)
- }
-
- @Test
- fun equals_hashCode_toString_equalByReference_areEqual() {
- assertThat(issue1).isEqualTo(issue1)
- assertThat(issue1.hashCode()).isEqualTo(issue1.hashCode())
- assertThat(issue1.toString()).isEqualTo(issue1.toString())
- }
-
- @Test
- fun equals_hashCode_toString_equalByValue_areEqual() {
- val issue = SafetyCenterIssue.Builder("an id")
- .setTitle("a title")
- .setSubtitle("In the neighborhood")
- .setSummary("Please acknowledge this")
- .setSeverityLevel(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_OK)
- .setActions(listOf(action1))
- .build()
- val equivalentIssue = SafetyCenterIssue.Builder("an id")
- .setTitle("a title")
- .setSubtitle("In the neighborhood")
- .setSummary("Please acknowledge this")
- .setSeverityLevel(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_OK)
- .setActions(listOf(action1))
- .build()
-
- assertThat(issue).isEqualTo(equivalentIssue)
- assertThat(issue.hashCode()).isEqualTo(equivalentIssue.hashCode())
- assertThat(issue.toString()).isEqualTo(equivalentIssue.toString())
- }
-
- @Test
- fun equals_hashCode_toString_fromCopyBuilder() {
- val copyOfIssue1 = SafetyCenterIssue.Builder(issue1).build()
-
- assertThat(copyOfIssue1).isEqualTo(issue1)
- assertThat(copyOfIssue1.hashCode()).isEqualTo(issue1.hashCode())
- assertThat(copyOfIssue1.toString()).isEqualTo(issue1.toString())
- }
-
- @Test
- fun equals_toString_differentIds_areNotEqual() {
- val differentFromIssue1 = SafetyCenterIssue.Builder(issue1)
- .setId("a different id")
- .build()
-
- assertThat(differentFromIssue1).isNotEqualTo(issue1)
- assertThat(differentFromIssue1.toString()).isNotEqualTo(issue1.toString())
- }
-
- @Test
- fun equals_toString_differentTitles_areNotEqual() {
- val differentFromIssue1 = SafetyCenterIssue.Builder(issue1)
- .setTitle("a different title")
- .build()
-
- assertThat(differentFromIssue1).isNotEqualTo(issue1)
- assertThat(differentFromIssue1.toString()).isNotEqualTo(issue1.toString())
- }
-
- @Test
- fun equals_toString_differentSubtitles_areNotEqual() {
- val differentFromIssue1 = SafetyCenterIssue.Builder(issue1)
- .setSubtitle("a different subtitle")
- .build()
-
- assertThat(differentFromIssue1).isNotEqualTo(issue1)
- assertThat(differentFromIssue1.toString()).isNotEqualTo(issue1.toString())
- }
-
- @Test
- fun equals_toString_differentSummaries_areNotEqual() {
- val differentFromIssue1 = SafetyCenterIssue.Builder(issue1)
- .setSummary("a different summary")
- .build()
-
- assertThat(differentFromIssue1).isNotEqualTo(issue1)
- assertThat(differentFromIssue1.toString()).isNotEqualTo(issue1.toString())
- }
-
- @Test
- fun equals_toString_differentSeverityLevels_areNotEqual() {
- val differentFromIssue1 = SafetyCenterIssue.Builder(issue1)
- .setSeverityLevel(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_CRITICAL_WARNING)
- .build()
-
- assertThat(differentFromIssue1).isNotEqualTo(issue1)
- assertThat(differentFromIssue1.toString()).isNotEqualTo(issue1.toString())
- }
-
- @Test
- fun equals_toString_differentIsDismissibleValues_areNotEqual() {
- val differentFromIssue1 = SafetyCenterIssue.Builder(issue1)
- .setDismissible(false)
- .build()
-
- assertThat(differentFromIssue1).isNotEqualTo(issue1)
- assertThat(differentFromIssue1.toString()).isNotEqualTo(issue1.toString())
- }
-
- @Test
- fun equals_toString_differentShouldConfirmDismissalValues_areNotEqual() {
- val differentFromIssue1 = SafetyCenterIssue.Builder(issue1)
- .setShouldConfirmDismissal(false)
- .build()
-
- assertThat(differentFromIssue1).isNotEqualTo(issue1)
- assertThat(differentFromIssue1.toString()).isNotEqualTo(issue1.toString())
- }
-
- @Test
- fun equals_toString_differentActions_areNotEqual() {
- val differentFromIssue1 = SafetyCenterIssue.Builder(issue1)
- .setActions(listOf(action2))
- .build()
-
- assertThat(differentFromIssue1).isNotEqualTo(issue1)
- assertThat(differentFromIssue1.toString()).isNotEqualTo(issue1.toString())
+ assertThat(issueWithRequiredFieldsOnly.describeContents()).isEqualTo(0)
+ }
+
+ @Test
+ fun parcelRoundTrip_recreatesEqual() {
+ assertThat(issue1).recreatesEqual(SafetyCenterIssue.CREATOR)
+ assertThat(issueWithRequiredFieldsOnly).recreatesEqual(SafetyCenterIssue.CREATOR)
+ }
+
+ @Test
+ fun equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
+ EqualsHashCodeToStringTester()
+ .addEqualityGroup(issue1, SafetyCenterIssue.Builder(issue1).build())
+ .addEqualityGroup(issueWithRequiredFieldsOnly)
+ .addEqualityGroup(
+ SafetyCenterIssue.Builder("an id", "a title", "Please acknowledge this")
+ .setSubtitle("In the neighborhood")
+ .setSeverityLevel(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_OK)
+ .setActions(listOf(action1))
+ .build(),
+ SafetyCenterIssue.Builder("an id", "a title", "Please acknowledge this")
+ .setSubtitle("In the neighborhood")
+ .setSeverityLevel(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_OK)
+ .setActions(listOf(action1))
+ .build()
+ )
+ .addEqualityGroup(SafetyCenterIssue.Builder(issue1).setId("a different id").build())
+ .addEqualityGroup(
+ SafetyCenterIssue.Builder(issue1).setTitle("a different title").build())
+ .addEqualityGroup(
+ SafetyCenterIssue.Builder(issue1).setSubtitle("a different subtitle").build()
+ )
+ .addEqualityGroup(
+ SafetyCenterIssue.Builder(issue1).setSummary("a different summary").build())
+ .addEqualityGroup(
+ SafetyCenterIssue.Builder(issue1)
+ .setSeverityLevel(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_CRITICAL_WARNING)
+ .build()
+ )
+ .addEqualityGroup(SafetyCenterIssue.Builder(issue1).setDismissible(false).build())
+ .addEqualityGroup(
+ SafetyCenterIssue.Builder(issue1).setShouldConfirmDismissal(false).build())
+ .addEqualityGroup(SafetyCenterIssue.Builder(issue1).setActions(listOf(action2)).build())
+ .test()
}
@Test
@@ -350,154 +265,69 @@ class SafetyCenterIssueTest {
@Test
fun action_describeContents_returns0() {
assertThat(action1.describeContents()).isEqualTo(0)
- }
-
- @Test
- fun action_createFromParcel_withWriteToParcel_returnsEquivalentObject() {
- val parcel = Parcel.obtain()
-
- action1.writeToParcel(parcel, /* flags= */ 0)
-
- parcel.setDataPosition(0)
- val fromParcel = SafetyCenterIssue.Action.CREATOR.createFromParcel(parcel)
- parcel.recycle()
-
- assertThat(fromParcel).isEqualTo(action1)
- }
-
- @Test
- fun action_equals_hashCode_toString_equalByReference_areEqual() {
- assertThat(action1).isEqualTo(action1)
- assertThat(action1.hashCode()).isEqualTo(action1.hashCode())
- assertThat(action1.toString()).isEqualTo(action1.toString())
- }
-
- @Test
- fun action_equals_hashCode_toString_equalByValue_areEqual() {
- val action = SafetyCenterIssue.Action.Builder("an_id")
- .setLabel("a label")
- .setPendingIntent(pendingIntent1)
- .setWillResolve(true)
- .setIsInFlight(true)
- .setSuccessMessage("a success message")
- .build()
- val equivalentAction = SafetyCenterIssue.Action.Builder("an_id")
- .setLabel("a label")
- .setPendingIntent(pendingIntent1)
- .setWillResolve(true)
- .setIsInFlight(true)
- .setSuccessMessage("a success message")
- .build()
-
- assertThat(action).isEqualTo(equivalentAction)
- assertThat(action.toString()).isEqualTo(equivalentAction.toString())
- }
-
- @Test
- fun action_equals_toString_differentIds_areNotEqual() {
- val action = SafetyCenterIssue.Action.Builder("an_id")
- .setLabel("a label")
- .setPendingIntent(pendingIntent1)
- .setSuccessMessage("a success message")
- .build()
- val differentAction = SafetyCenterIssue.Action.Builder("a_different_id")
- .setLabel("a label")
- .setPendingIntent(pendingIntent1)
- .setSuccessMessage("a success message")
- .build()
-
- assertThat(action).isNotEqualTo(differentAction)
- assertThat(action.toString()).isNotEqualTo(differentAction.toString())
- }
-
- @Test
- fun action_equals_toString_differentLabels_areNotEqual() {
- val action = SafetyCenterIssue.Action.Builder("an_id")
- .setLabel("a label")
- .setPendingIntent(pendingIntent1)
- .setSuccessMessage("a success message")
- .build()
- val differentAction = SafetyCenterIssue.Action.Builder("an_id")
- .setLabel("a different label")
- .setPendingIntent(pendingIntent1)
- .setSuccessMessage("a success message")
- .build()
-
- assertThat(action).isNotEqualTo(differentAction)
- assertThat(action.toString()).isNotEqualTo(differentAction.toString())
- }
-
- @Test
- fun action_equals_toString_differentPendingIntents_areNotEqual() {
- val action = SafetyCenterIssue.Action.Builder("an_id")
- .setLabel("a label")
- .setPendingIntent(pendingIntent1)
- .setSuccessMessage("a success message")
- .build()
- val differentAction = SafetyCenterIssue.Action.Builder("an_id")
- .setLabel("a label")
- .setPendingIntent(pendingIntent2)
- .setSuccessMessage("a success message")
- .build()
-
- assertThat(action).isNotEqualTo(differentAction)
- assertThat(action.toString()).isNotEqualTo(differentAction.toString())
- }
-
- @Test
- fun action_equals_toString_differentWillResolveValues_areNotEqual() {
- val action = SafetyCenterIssue.Action.Builder("an_id")
- .setLabel("a label")
- .setPendingIntent(pendingIntent1)
- .setWillResolve(true)
- .setSuccessMessage("a success message")
- .build()
- val differentAction = SafetyCenterIssue.Action.Builder("an_id")
- .setLabel("a label")
- .setPendingIntent(pendingIntent1)
- .setWillResolve(false)
- .setSuccessMessage("a success message")
- .build()
-
- assertThat(action).isNotEqualTo(differentAction)
- assertThat(action.toString()).isNotEqualTo(differentAction.toString())
- }
-
- @Test
- fun action_equals_toString_differentInFlightValues_areNotEqual() {
- val action = SafetyCenterIssue.Action.Builder("an_id")
- .setLabel("a label")
- .setPendingIntent(pendingIntent1)
- .setWillResolve(true)
- .setIsInFlight(true)
- .setSuccessMessage("a success message")
- .build()
- val differentAction = SafetyCenterIssue.Action.Builder("an_id")
- .setLabel("a label")
- .setPendingIntent(pendingIntent1)
- .setWillResolve(true)
- .setIsInFlight(false)
- .setSuccessMessage("a success message")
- .build()
-
- assertThat(action).isNotEqualTo(differentAction)
- assertThat(action.toString()).isNotEqualTo(differentAction.toString())
- }
-
- @Test
- fun action_equals_toString_differentSuccessMessages_areNotEqual() {
- val action = SafetyCenterIssue.Action.Builder("an_id")
- .setLabel("a label")
- .setPendingIntent(pendingIntent1)
- .setSuccessMessage("a success message")
- .build()
- val differentAction = SafetyCenterIssue.Action.Builder("an_id")
- .setLabel("a label")
- .setPendingIntent(pendingIntent1)
- .setSuccessMessage("a different success message")
- .build()
-
- assertThat(action).isNotEqualTo(differentAction)
- assertThat(action.toString()).isNotEqualTo(differentAction.toString())
- }
-} \ No newline at end of file
+ assertThat(action2.describeContents()).isEqualTo(0)
+ }
+
+ @Test
+ fun action_parcelRoundTrip_recreatesEqual() {
+ assertThat(action1).recreatesEqual(SafetyCenterIssue.Action.CREATOR)
+ assertThat(action2).recreatesEqual(SafetyCenterIssue.Action.CREATOR)
+ }
+
+ @Test
+ fun action_equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
+ EqualsHashCodeToStringTester()
+ .addEqualityGroup(action1)
+ .addEqualityGroup(action2)
+ .addEqualityGroup(
+ SafetyCenterIssue.Action.Builder("an_id", "a label", pendingIntent1)
+ .setWillResolve(true)
+ .setIsInFlight(true)
+ .setSuccessMessage("a success message")
+ .build(),
+ SafetyCenterIssue.Action.Builder("an_id", "a label", pendingIntent1)
+ .setWillResolve(true)
+ .setIsInFlight(true)
+ .setSuccessMessage("a success message")
+ .build()
+ )
+ .addEqualityGroup(
+ SafetyCenterIssue.Action.Builder("an_id", "a label", pendingIntent1)
+ .setSuccessMessage("a success message")
+ .build()
+ )
+ .addEqualityGroup(
+ SafetyCenterIssue.Action.Builder("a_different_id", "a label", pendingIntent1)
+ .setSuccessMessage("a success message")
+ .build()
+ )
+ .addEqualityGroup(
+ SafetyCenterIssue.Action.Builder("an_id", "a different label", pendingIntent1)
+ .setSuccessMessage("a success message")
+ .build()
+ )
+ .addEqualityGroup(
+ SafetyCenterIssue.Action.Builder("an_id", "a label", pendingIntent2)
+ .setSuccessMessage("a success message")
+ .build()
+ )
+ .addEqualityGroup(
+ SafetyCenterIssue.Action.Builder("an_id", "a label", pendingIntent1)
+ .setWillResolve(true)
+ .setSuccessMessage("a success message")
+ .build()
+ )
+ .addEqualityGroup(
+ SafetyCenterIssue.Action.Builder("an_id", "a label", pendingIntent1)
+ .setIsInFlight(true)
+ .setSuccessMessage("a success message")
+ .build()
+ )
+ .addEqualityGroup(
+ SafetyCenterIssue.Action.Builder("an_id", "a label", pendingIntent1)
+ .setSuccessMessage("a different success message")
+ .build()
+ )
+ .test()
+ }
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt
index af785eecf..5455c2218 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt
@@ -35,48 +35,51 @@ import android.safetycenter.SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_UNKNOWN
import android.safetycenter.SafetyEvent
import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
import android.safetycenter.SafetySourceData
+import android.safetycenter.SafetySourceData.SEVERITY_LEVEL_CRITICAL_WARNING
+import android.safetycenter.SafetySourceData.SEVERITY_LEVEL_INFORMATION
+import android.safetycenter.SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED
import android.safetycenter.SafetySourceErrorDetails
import android.safetycenter.SafetySourceIssue
-import android.safetycenter.SafetySourceIssue.SEVERITY_LEVEL_CRITICAL_WARNING
import android.safetycenter.SafetySourceStatus
-import android.safetycenter.SafetySourceStatus.STATUS_LEVEL_CRITICAL_WARNING
-import android.safetycenter.SafetySourceStatus.STATUS_LEVEL_NONE
-import android.safetycenter.SafetySourceStatus.STATUS_LEVEL_OK
import android.safetycenter.config.SafetyCenterConfig
import android.safetycenter.config.SafetySource
import android.safetycenter.config.SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC
import android.safetycenter.config.SafetySourcesGroup
-import android.safetycenter.testing.SafetyCenterFlags
-import android.safetycenter.testing.SafetyCenterFlags.deviceSupportsSafetyCenter
-import android.safetycenter.testing.SafetySourceBroadcastReceiver
-import android.safetycenter.testing.addOnSafetyCenterDataChangedListenerWithPermission
-import android.safetycenter.testing.clearAllSafetySourceDataWithPermission
-import android.safetycenter.testing.clearSafetyCenterConfigOverrideWithPermission
-import android.safetycenter.testing.getSafetyCenterDataWithPermission
-import android.safetycenter.testing.getSafetySourceDataWithPermission
-import android.safetycenter.testing.isSafetyCenterEnabledWithPermission
-import android.safetycenter.testing.refreshSafetySourcesWithPermission
-import android.safetycenter.testing.removeOnSafetyCenterDataChangedListenerWithPermission
-import android.safetycenter.testing.reportSafetySourceErrorWithPermission
-import android.safetycenter.testing.setSafetyCenterConfigOverrideWithPermission
-import android.safetycenter.testing.setSafetySourceDataWithPermission
+import android.safetycenter.cts.testing.Coroutines.TIMEOUT_LONG
+import android.safetycenter.cts.testing.Coroutines.TIMEOUT_SHORT
+import android.safetycenter.cts.testing.Coroutines.runBlockingWithTimeout
+import android.safetycenter.cts.testing.FakeExecutor
+import android.safetycenter.cts.testing.SafetyCenterApisWithShellPermissions.addOnSafetyCenterDataChangedListenerWithPermission
+import android.safetycenter.cts.testing.SafetyCenterApisWithShellPermissions.clearAllSafetySourceDataForTestsWithPermission
+import android.safetycenter.cts.testing.SafetyCenterApisWithShellPermissions.clearSafetyCenterConfigForTestsWithPermission
+import android.safetycenter.cts.testing.SafetyCenterApisWithShellPermissions.getSafetyCenterConfigWithPermission
+import android.safetycenter.cts.testing.SafetyCenterApisWithShellPermissions.getSafetyCenterDataWithPermission
+import android.safetycenter.cts.testing.SafetyCenterApisWithShellPermissions.getSafetySourceDataWithPermission
+import android.safetycenter.cts.testing.SafetyCenterApisWithShellPermissions.isSafetyCenterEnabledWithPermission
+import android.safetycenter.cts.testing.SafetyCenterApisWithShellPermissions.refreshSafetySourcesWithPermission
+import android.safetycenter.cts.testing.SafetyCenterApisWithShellPermissions.removeOnSafetyCenterDataChangedListenerWithPermission
+import android.safetycenter.cts.testing.SafetyCenterApisWithShellPermissions.reportSafetySourceErrorWithPermission
+import android.safetycenter.cts.testing.SafetyCenterApisWithShellPermissions.setSafetyCenterConfigForTestsWithPermission
+import android.safetycenter.cts.testing.SafetyCenterApisWithShellPermissions.setSafetySourceDataWithPermission
+import android.safetycenter.cts.testing.SafetyCenterFlags
+import android.safetycenter.cts.testing.SafetyCenterFlags.deviceSupportsSafetyCenter
+import android.safetycenter.cts.testing.SafetySourceBroadcastReceiver
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress
import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
import com.google.common.truth.Truth.assertThat
import com.google.common.util.concurrent.MoreExecutors.directExecutor
+import java.time.Duration
+import kotlin.test.assertFailsWith
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.withTimeout
+import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED
import org.junit.After
import org.junit.Assume.assumeTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import java.time.Duration
-import kotlin.test.assertFailsWith
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
@@ -90,35 +93,28 @@ class SafetyCenterManagerTest {
Intent(ACTION_SAFETY_CENTER),
FLAG_IMMUTABLE
)
- private val safetySourceDataNone =
+ private val safetySourceDataUnspecified =
SafetySourceData.Builder()
.setStatus(
- SafetySourceStatus.Builder(
- "None title",
- "None summary",
- STATUS_LEVEL_NONE,
- somePendingIntent
- )
+ SafetySourceStatus.Builder("None title", "None summary", SEVERITY_LEVEL_UNSPECIFIED)
+ .setEnabled(false)
.build()
)
.build()
- private val safetySourceDataOk =
+ private val safetySourceDataInformation =
SafetySourceData.Builder()
.setStatus(
- SafetySourceStatus.Builder("Ok title", "Ok summary", STATUS_LEVEL_OK,
- somePendingIntent)
+ SafetySourceStatus.Builder("Ok title", "Ok summary", SEVERITY_LEVEL_INFORMATION)
+ .setPendingIntent(somePendingIntent)
.build()
)
.build()
private val safetySourceDataCritical =
SafetySourceData.Builder()
.setStatus(
- SafetySourceStatus.Builder(
- "Critical title",
- "Critical summary",
- STATUS_LEVEL_CRITICAL_WARNING,
- somePendingIntent
- )
+ SafetySourceStatus.Builder("Critical title", "Critical summary",
+ SEVERITY_LEVEL_CRITICAL_WARNING)
+ .setPendingIntent(somePendingIntent)
.build()
)
.addIssue(
@@ -137,29 +133,30 @@ class SafetyCenterManagerTest {
.build()
)
.build()
- private val listener = object : OnSafetyCenterDataChangedListener {
- private val dataChannel = Channel<SafetyCenterData>()
- private val errorChannel = Channel<SafetyCenterErrorDetails>()
+ private val listener =
+ object : OnSafetyCenterDataChangedListener {
+ private val dataChannel = Channel<SafetyCenterData>(UNLIMITED)
+ private val errorChannel = Channel<SafetyCenterErrorDetails>(UNLIMITED)
- override fun onSafetyCenterDataChanged(data: SafetyCenterData) {
- runBlockingWithTimeout { dataChannel.send(data) }
- }
+ override fun onSafetyCenterDataChanged(data: SafetyCenterData) {
+ runBlockingWithTimeout { dataChannel.send(data) }
+ }
- override fun onError(errorDetails: SafetyCenterErrorDetails) {
- runBlockingWithTimeout { errorChannel.send(errorDetails) }
- }
+ override fun onError(errorDetails: SafetyCenterErrorDetails) {
+ runBlockingWithTimeout { errorChannel.send(errorDetails) }
+ }
- fun receiveSafetyCenterData(timeout: Duration = TIMEOUT_LONG) =
- runBlockingWithTimeout(timeout) { dataChannel.receive() }
+ fun receiveSafetyCenterData(timeout: Duration = TIMEOUT_LONG) =
+ runBlockingWithTimeout(timeout) { dataChannel.receive() }
- fun receiveSafetyCenterErrorDetails(timeout: Duration = TIMEOUT_LONG) =
- runBlockingWithTimeout(timeout) { errorChannel.receive() }
+ fun receiveSafetyCenterErrorDetails(timeout: Duration = TIMEOUT_LONG) =
+ runBlockingWithTimeout(timeout) { errorChannel.receive() }
- fun cancelChannels() {
- dataChannel.cancel()
- errorChannel.cancel()
+ fun cancelChannels() {
+ dataChannel.cancel()
+ errorChannel.cancel()
+ }
}
- }
@Before
fun assumeDeviceSupportsSafetyCenterToRunTests() {
@@ -171,8 +168,8 @@ class SafetyCenterManagerTest {
fun clearDataBetweenTest() {
SafetyCenterFlags.setSafetyCenterEnabled(true)
safetyCenterManager.removeOnSafetyCenterDataChangedListenerWithPermission(listener)
- safetyCenterManager.clearAllSafetySourceDataWithPermission()
- safetyCenterManager.clearSafetyCenterConfigOverrideWithPermission()
+ safetyCenterManager.clearAllSafetySourceDataForTestsWithPermission()
+ safetyCenterManager.clearSafetyCenterConfigForTestsWithPermission()
SafetySourceBroadcastReceiver.reset()
}
@@ -204,25 +201,25 @@ class SafetyCenterManagerTest {
@Test
fun setSafetySourceData_validId_setsValue() {
- safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_CONFIG)
+ safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(CTS_CONFIG)
safetyCenterManager.setSafetySourceDataWithPermission(
CTS_SOURCE_ID,
- safetySourceDataNone,
+ safetySourceDataUnspecified,
EVENT_SOURCE_STATE_CHANGED
)
val apiSafetySourceData =
safetyCenterManager.getSafetySourceDataWithPermission(CTS_SOURCE_ID)
- assertThat(apiSafetySourceData).isEqualTo(safetySourceDataNone)
+ assertThat(apiSafetySourceData).isEqualTo(safetySourceDataUnspecified)
}
@Test
fun setSafetySourceData_twice_replacesValue() {
- safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_CONFIG)
+ safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(CTS_CONFIG)
safetyCenterManager.setSafetySourceDataWithPermission(
CTS_SOURCE_ID,
- safetySourceDataNone,
+ safetySourceDataUnspecified,
EVENT_SOURCE_STATE_CHANGED
)
@@ -239,10 +236,10 @@ class SafetyCenterManagerTest {
@Test
fun setSafetySourceData_null_clearsValue() {
- safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_CONFIG)
+ safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(CTS_CONFIG)
safetyCenterManager.setSafetySourceDataWithPermission(
CTS_SOURCE_ID,
- safetySourceDataNone,
+ safetySourceDataUnspecified,
EVENT_SOURCE_STATE_CHANGED
)
@@ -263,7 +260,7 @@ class SafetyCenterManagerTest {
safetyCenterManager.setSafetySourceDataWithPermission(
CTS_SOURCE_ID,
- safetySourceDataNone,
+ safetySourceDataUnspecified,
EVENT_SOURCE_STATE_CHANGED
)
@@ -277,7 +274,7 @@ class SafetyCenterManagerTest {
assertFailsWith(SecurityException::class) {
safetyCenterManager.setSafetySourceData(
CTS_SOURCE_ID,
- safetySourceDataNone,
+ safetySourceDataUnspecified,
EVENT_SOURCE_STATE_CHANGED
)
}
@@ -285,7 +282,7 @@ class SafetyCenterManagerTest {
@Test
fun getSafetySourceData_validId_noData_returnsNull() {
- safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_CONFIG)
+ safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(CTS_CONFIG)
val apiSafetySourceData =
safetyCenterManager.getSafetySourceDataWithPermission(CTS_SOURCE_ID)
@@ -306,6 +303,8 @@ class SafetyCenterManagerTest {
directExecutor(),
listener
)
+ // Receive initial data.
+ listener.receiveSafetyCenterData()
safetyCenterManager.reportSafetySourceErrorWithPermission(
CTS_SOURCE_ID,
@@ -329,7 +328,7 @@ class SafetyCenterManagerTest {
@Test
fun refreshSafetySources_withRefreshReasonRescanButtonClick_sourceSendsRescanData() {
- safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_CONFIG)
+ safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(CTS_CONFIG)
SafetySourceBroadcastReceiver.safetySourceId = CTS_SOURCE_ID
SafetySourceBroadcastReceiver.safetySourceDataOnRescanClick = safetySourceDataCritical
@@ -344,21 +343,21 @@ class SafetyCenterManagerTest {
@Test
fun refreshSafetySources_withRefreshReasonPageOpen_sourceSendsPageOpenData() {
- safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_CONFIG)
+ safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(CTS_CONFIG)
SafetySourceBroadcastReceiver.safetySourceId = CTS_SOURCE_ID
- SafetySourceBroadcastReceiver.safetySourceDataOnPageOpen = safetySourceDataOk
+ SafetySourceBroadcastReceiver.safetySourceDataOnPageOpen = safetySourceDataInformation
safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
REFRESH_REASON_PAGE_OPEN)
val apiSafetySourceData =
safetyCenterManager.getSafetySourceDataWithPermission(CTS_SOURCE_ID)
- assertThat(apiSafetySourceData).isEqualTo(safetySourceDataOk)
+ assertThat(apiSafetySourceData).isEqualTo(safetySourceDataInformation)
}
@Test
fun refreshSafetySources_whenReceiverDoesNotHaveSendingPermission_sourceDoesNotSendData() {
- safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_CONFIG)
+ safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(CTS_CONFIG)
SafetySourceBroadcastReceiver.safetySourceId = CTS_SOURCE_ID
SafetySourceBroadcastReceiver.safetySourceDataOnRescanClick = safetySourceDataCritical
@@ -375,13 +374,15 @@ class SafetyCenterManagerTest {
@Test
fun refreshSafetySources_withFlagDisabled_noOp() {
SafetyCenterFlags.setSafetyCenterEnabled(false)
- safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_CONFIG)
+ safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(CTS_CONFIG)
SafetySourceBroadcastReceiver.safetySourceId = CTS_SOURCE_ID
- SafetySourceBroadcastReceiver.safetySourceDataOnPageOpen = safetySourceDataOk
+ SafetySourceBroadcastReceiver.safetySourceDataOnPageOpen = safetySourceDataInformation
assertFailsWith(TimeoutCancellationException::class) {
safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
- REFRESH_REASON_PAGE_OPEN, TIMEOUT_SHORT)
+ REFRESH_REASON_PAGE_OPEN,
+ TIMEOUT_SHORT
+ )
}
val apiSafetySourceData =
safetyCenterManager.getSafetySourceDataWithPermission(CTS_SOURCE_ID)
@@ -405,8 +406,21 @@ class SafetyCenterManagerTest {
}
@Test
+ fun getSafetyCenterConfig_isNotNull() {
+ val config = safetyCenterManager.getSafetyCenterConfigWithPermission()
+
+ // TODO(b/225152057): Assert on content.
+ assertThat(config).isNotNull()
+ }
+
+ @Test
+ fun getSafetyCenterConfig_withoutPermission_throwsSecurityException() {
+ assertFailsWith(SecurityException::class) { safetyCenterManager.safetyCenterConfig }
+ }
+
+ @Test
fun getSafetyCenterData_withoutDataProvided_returnsDataFromConfig() {
- safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_CONFIG)
+ safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(CTS_CONFIG)
val apiSafetyCenterData = safetyCenterManager.getSafetyCenterDataWithPermission()
@@ -416,10 +430,10 @@ class SafetyCenterManagerTest {
@Test
fun getSafetyCenterData_withSomeDataProvided_returnsDataProvided() {
- safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_CONFIG)
+ safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(CTS_CONFIG)
safetyCenterManager.setSafetySourceDataWithPermission(
CTS_SOURCE_ID,
- safetySourceDataNone,
+ safetySourceDataUnspecified,
EVENT_SOURCE_STATE_CHANGED
)
@@ -431,10 +445,10 @@ class SafetyCenterManagerTest {
@Test
fun getSafetyCenterData_withUpdatedData_returnsUpdatedData() {
- safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_CONFIG)
+ safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(CTS_CONFIG)
safetyCenterManager.setSafetySourceDataWithPermission(
CTS_SOURCE_ID,
- safetySourceDataOk,
+ safetySourceDataInformation,
EVENT_SOURCE_STATE_CHANGED
)
val previousApiSafetyCenterData =
@@ -454,20 +468,21 @@ class SafetyCenterManagerTest {
@Test
fun getSafetyCenterData_withFlagDisabled_returnsDefaultData() {
SafetyCenterFlags.setSafetyCenterEnabled(false)
- safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_CONFIG)
+ safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(CTS_CONFIG)
val apiSafetyCenterData = safetyCenterManager.getSafetyCenterDataWithPermission()
- assertThat(apiSafetyCenterData).isEqualTo(SafetyCenterData(
- SafetyCenterStatus.Builder()
- .setSeverityLevel(OVERALL_SEVERITY_LEVEL_UNKNOWN)
- .setTitle("Unknown")
- .setSummary("Unknown safety status")
- .build(),
- emptyList(),
- emptyList(),
- emptyList()
- ))
+ assertThat(apiSafetyCenterData)
+ .isEqualTo(
+ SafetyCenterData(
+ SafetyCenterStatus.Builder("Unknown", "Unknown safety status")
+ .setSeverityLevel(OVERALL_SEVERITY_LEVEL_UNKNOWN)
+ .build(),
+ emptyList(),
+ emptyList(),
+ emptyList()
+ )
+ )
}
@Test
@@ -477,7 +492,7 @@ class SafetyCenterManagerTest {
@Test
fun addOnSafetyCenterDataChangedListener_listenerCalledWithSafetyCenterDataFromConfig() {
- safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_CONFIG)
+ safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(CTS_CONFIG)
safetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(
directExecutor(),
listener
@@ -490,7 +505,7 @@ class SafetyCenterManagerTest {
@Test
fun addOnSafetyCenterDataChangedListener_listenerCalledOnSafetySourceData() {
- safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_CONFIG)
+ safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(CTS_CONFIG)
safetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(
directExecutor(),
listener
@@ -500,7 +515,7 @@ class SafetyCenterManagerTest {
safetyCenterManager.setSafetySourceDataWithPermission(
CTS_SOURCE_ID,
- safetySourceDataOk,
+ safetySourceDataInformation,
EVENT_SOURCE_STATE_CHANGED
)
val safetyCenterDataFromListener = listener.receiveSafetyCenterData()
@@ -511,7 +526,7 @@ class SafetyCenterManagerTest {
@Test
fun addOnSafetyCenterDataChangedListener_listenerCalledWhenSafetySourceDataChanges() {
- safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_CONFIG)
+ safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(CTS_CONFIG)
safetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(
directExecutor(),
listener
@@ -520,7 +535,7 @@ class SafetyCenterManagerTest {
listener.receiveSafetyCenterData()
safetyCenterManager.setSafetySourceDataWithPermission(
CTS_SOURCE_ID,
- safetySourceDataOk,
+ safetySourceDataInformation,
EVENT_SOURCE_STATE_CHANGED
)
// Receive update from #setSafetySourceData call.
@@ -539,7 +554,7 @@ class SafetyCenterManagerTest {
@Test
fun addOnSafetyCenterDataChangedListener_listenerCalledWhenSafetySourceDataCleared() {
- safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_CONFIG)
+ safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(CTS_CONFIG)
safetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(
directExecutor(),
listener
@@ -548,7 +563,7 @@ class SafetyCenterManagerTest {
listener.receiveSafetyCenterData()
safetyCenterManager.setSafetySourceDataWithPermission(
CTS_SOURCE_ID,
- safetySourceDataOk,
+ safetySourceDataInformation,
EVENT_SOURCE_STATE_CHANGED
)
// Receive update from #setSafetySourceData call.
@@ -567,7 +582,7 @@ class SafetyCenterManagerTest {
@Test
fun addOnSafetyCenterDataChangedListener_listenerNotCalledWhenSafetySourceDataStaysNull() {
- safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_CONFIG)
+ safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(CTS_CONFIG)
safetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(
directExecutor(),
listener
@@ -588,7 +603,7 @@ class SafetyCenterManagerTest {
@Test
fun addOnSafetyCenterDataChangedListener_listenerNotCalledWhenSafetySourceDataDoesntChange() {
- safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_CONFIG)
+ safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(CTS_CONFIG)
safetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(
directExecutor(),
listener
@@ -597,7 +612,7 @@ class SafetyCenterManagerTest {
listener.receiveSafetyCenterData()
safetyCenterManager.setSafetySourceDataWithPermission(
CTS_SOURCE_ID,
- safetySourceDataOk,
+ safetySourceDataInformation,
EVENT_SOURCE_STATE_CHANGED
)
// Receive update from #setSafetySourceData call.
@@ -605,7 +620,7 @@ class SafetyCenterManagerTest {
safetyCenterManager.setSafetySourceDataWithPermission(
CTS_SOURCE_ID,
- safetySourceDataOk,
+ safetySourceDataInformation,
EVENT_SOURCE_STATE_CHANGED
)
@@ -617,7 +632,7 @@ class SafetyCenterManagerTest {
@Test
fun addOnSafetyCenterDataChangedListener_withFlagDisabled_listenerNotCalled() {
SafetyCenterFlags.setSafetyCenterEnabled(false)
- safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_CONFIG)
+ safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(CTS_CONFIG)
safetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(
directExecutor(),
@@ -637,28 +652,34 @@ class SafetyCenterManagerTest {
}
@Test
+ // Permission is held for the entire test to avoid a racy scenario where the shell identity is
+ // dropped while it's being acquired on another thread.
fun addOnSafetyCenterDataChangedListener_oneShot_doesntDeadlock() {
- val oneShotListener =
- object : OnSafetyCenterDataChangedListener {
- override fun onSafetyCenterDataChanged(safetyCenterData: SafetyCenterData) {
- safetyCenterManager.removeOnSafetyCenterDataChangedListenerWithPermission(this)
- listener.onSafetyCenterDataChanged(safetyCenterData)
- }
- }
- safetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(
- directExecutor(),
- oneShotListener
+ callWithShellPermissionIdentity(
+ {
+ val oneShotListener =
+ object : OnSafetyCenterDataChangedListener {
+ override fun onSafetyCenterDataChanged(safetyCenterData: SafetyCenterData) {
+ safetyCenterManager.removeOnSafetyCenterDataChangedListener(this)
+ listener.onSafetyCenterDataChanged(safetyCenterData)
+ }
+ }
+ safetyCenterManager.addOnSafetyCenterDataChangedListener(directExecutor(),
+ oneShotListener)
+
+ // Check that we don't deadlock when using a one-shot listener: this is because
+ // adding the listener could call the listener while holding a lock on the binder
+ // thread-pool; causing a deadlock when attempting to call the `SafetyCenterManager`
+ // from that listener.
+ listener.receiveSafetyCenterData()
+ },
+ MANAGE_SAFETY_CENTER
)
-
- // Check that we don't deadlock when using a one-shot listener: this is because adding the
- // listener could call the listener while holding a lock on the binder thread-pool; causing
- // a deadlock when attempting to call the `SafetyCenterManager` from that listener.
- listener.receiveSafetyCenterData()
}
@Test
fun removeOnSafetyCenterDataChangedListener_listenerNotCalledOnSafetySourceData() {
- safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_CONFIG)
+ safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(CTS_CONFIG)
safetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(
directExecutor(),
listener
@@ -669,9 +690,36 @@ class SafetyCenterManagerTest {
safetyCenterManager.removeOnSafetyCenterDataChangedListenerWithPermission(listener)
safetyCenterManager.setSafetySourceDataWithPermission(
CTS_SOURCE_ID,
- safetySourceDataOk,
+ safetySourceDataInformation,
+ EVENT_SOURCE_STATE_CHANGED
+ )
+
+ assertFailsWith(TimeoutCancellationException::class) {
+ listener.receiveSafetyCenterData(TIMEOUT_SHORT)
+ }
+ }
+
+ @Test
+ fun removeOnSafetyCenterDataChangedListener_listenerNeverCalledAfterRemoving() {
+ safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(CTS_CONFIG)
+ val fakeExecutor = FakeExecutor()
+ safetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(fakeExecutor,
+ listener)
+ // Receive initial data.
+ fakeExecutor.getNextTask().run()
+ listener.receiveSafetyCenterData()
+
+ safetyCenterManager.setSafetySourceDataWithPermission(
+ CTS_SOURCE_ID,
+ safetySourceDataInformation,
EVENT_SOURCE_STATE_CHANGED
)
+ val callListenerTask = fakeExecutor.getNextTask()
+ safetyCenterManager.removeOnSafetyCenterDataChangedListenerWithPermission(listener)
+ // Simulate the submitted task being run *after* the remove call completes. Our API should
+ // guard against this raciness, as users of this class likely don't expect their listener to
+ // be called after calling #removeOnSafetyCenterDataChangedListener.
+ callListenerTask.run()
assertFailsWith(TimeoutCancellationException::class) {
listener.receiveSafetyCenterData(TIMEOUT_SHORT)
@@ -705,21 +753,23 @@ class SafetyCenterManagerTest {
}
@Test
- fun clearAllSafetySourceData_withoutPermission_throwsSecurityException() {
- assertFailsWith(SecurityException::class) { safetyCenterManager.clearAllSafetySourceData() }
+ fun clearAllSafetySourceDataForTests_withoutPermission_throwsSecurityException() {
+ assertFailsWith(SecurityException::class) {
+ safetyCenterManager.clearAllSafetySourceDataForTests()
+ }
}
@Test
- fun setSafetyCenterConfigOverride_withoutPermission_throwsSecurityException() {
+ fun setSafetyCenterConfigForTests_withoutPermission_throwsSecurityException() {
assertFailsWith(SecurityException::class) {
- safetyCenterManager.setSafetyCenterConfigOverride(CTS_CONFIG)
+ safetyCenterManager.setSafetyCenterConfigForTests(CTS_CONFIG)
}
}
@Test
- fun clearSafetyCenterConfigOverride_withoutPermission_throwsSecurityException() {
+ fun clearSafetyCenterConfigForTests_withoutPermission_throwsSecurityException() {
assertFailsWith(SecurityException::class) {
- safetyCenterManager.clearSafetyCenterConfigOverride()
+ safetyCenterManager.clearSafetyCenterConfigForTests()
}
}
@@ -737,20 +787,8 @@ class SafetyCenterManagerTest {
)
}
- private fun <T> runBlockingWithTimeout(
- timeout: Duration = TIMEOUT_LONG,
- block: suspend () -> T
- ) =
- runBlocking {
- withTimeout(timeout.toMillis()) { block() }
- }
-
companion object {
private const val CTS_PACKAGE_NAME = "android.safetycenter.cts"
- private const val CTS_BROADCAST_RECEIVER_NAME =
- "android.safetycenter.testing.SafetySourceBroadcastReceiver"
- private val TIMEOUT_LONG: Duration = Duration.ofMillis(5000)
- private val TIMEOUT_SHORT: Duration = Duration.ofMillis(1000)
private val EVENT_SOURCE_STATE_CHANGED =
SafetyEvent.Builder(SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build()
private const val CTS_SOURCE_ID = "cts_source_id"
@@ -765,7 +803,6 @@ class SafetyCenterManagerTest {
.setTitleResId(android.R.string.ok)
.setSummaryResId(android.R.string.ok)
.setIntentAction(ACTION_SAFETY_CENTER)
- .setBroadcastReceiverClassName(CTS_BROADCAST_RECEIVER_NAME)
.setProfile(SafetySource.PROFILE_PRIMARY)
.build()
private val CTS_SOURCE_GROUP =
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterStaticEntryGroupTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterStaticEntryGroupTest.kt
index 9557833a2..f5893e6fc 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterStaticEntryGroupTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterStaticEntryGroupTest.kt
@@ -20,11 +20,12 @@ import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
import android.safetycenter.SafetyCenterStaticEntry
import android.safetycenter.SafetyCenterStaticEntryGroup
+import android.safetycenter.cts.testing.EqualsHashCodeToStringTester
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.ext.truth.os.ParcelableSubject.assertThat
import androidx.test.filters.SdkSuppress
import com.google.common.truth.Truth.assertThat
import org.junit.Test
@@ -35,39 +36,45 @@ import org.junit.runner.RunWith
class SafetyCenterStaticEntryGroupTest {
private val context: Context = ApplicationProvider.getApplicationContext()
- private val pendingIntent1 = PendingIntent.getActivity(
+ private val pendingIntent1 =
+ PendingIntent.getActivity(context, 0, Intent("Fake Data"), PendingIntent.FLAG_IMMUTABLE)
+ private val pendingIntent2 =
+ PendingIntent.getActivity(
context,
- /* requestCode= */ 0,
- Intent("Fake Data"),
- PendingIntent.FLAG_IMMUTABLE)
- private val pendingIntent2 = PendingIntent.getActivity(
- context,
- /* requestCode= */ 0,
+ 0,
Intent("Fake Different Data"),
- PendingIntent.FLAG_IMMUTABLE)
+ PendingIntent.FLAG_IMMUTABLE
+ )
private val staticEntry1 =
- SafetyCenterStaticEntry("an entry title", "an entry summary", pendingIntent1)
+ SafetyCenterStaticEntry.Builder("an entry title")
+ .setSummary("an entry summary")
+ .setPendingIntent(pendingIntent1)
+ .build()
private val staticEntry2 =
- SafetyCenterStaticEntry("another entry title", "another entry summary", pendingIntent2)
+ SafetyCenterStaticEntry.Builder("another entry title")
+ .setSummary("another entry summary")
+ .setPendingIntent(pendingIntent2)
+ .build()
private val staticEntryGroup =
- SafetyCenterStaticEntryGroup("a title", listOf(staticEntry1, staticEntry2))
+ SafetyCenterStaticEntryGroup("a title", listOf(staticEntry1, staticEntry2))
@Test
fun getTitle_returnsTitle() {
assertThat(SafetyCenterStaticEntryGroup("a title", listOf()).title).isEqualTo("a title")
assertThat(SafetyCenterStaticEntryGroup("another title", listOf()).title)
- .isEqualTo("another title")
+ .isEqualTo("another title")
}
@Test
fun getStaticEntries_returnsStaticEntries() {
assertThat(SafetyCenterStaticEntryGroup("", listOf(staticEntry1)).staticEntries)
- .containsExactly(staticEntry1)
+ .containsExactly(staticEntry1)
assertThat(
- SafetyCenterStaticEntryGroup("", listOf(staticEntry1, staticEntry2)).staticEntries)
- .containsExactly(staticEntry1, staticEntry2)
+ SafetyCenterStaticEntryGroup("", listOf(staticEntry1, staticEntry2)).staticEntries)
+ .containsExactly(staticEntry1, staticEntry2)
+ .inOrder()
assertThat(SafetyCenterStaticEntryGroup("", listOf()).staticEntries).isEmpty()
}
@@ -77,49 +84,24 @@ class SafetyCenterStaticEntryGroupTest {
}
@Test
- fun createFromParcel_withWriteToParcel_returnsEquivalentObject() {
- val parcel: Parcel = Parcel.obtain()
-
- staticEntryGroup.writeToParcel(parcel, 0 /* flags */)
- parcel.setDataPosition(0)
- val fromParcel = SafetyCenterStaticEntryGroup.CREATOR.createFromParcel(parcel)
- parcel.recycle()
-
- assertThat(fromParcel).isEqualTo(staticEntryGroup)
- }
-
- @Test
- fun equals_hashCode_toString_equalByReference_areEqual() {
- assertThat(staticEntryGroup).isEqualTo(staticEntryGroup)
- assertThat(staticEntryGroup.hashCode()).isEqualTo(staticEntryGroup.hashCode())
- assertThat(staticEntryGroup.toString()).isEqualTo(staticEntryGroup.toString())
+ fun parcelRoundTrip_recreatesEqual() {
+ assertThat(staticEntryGroup).recreatesEqual(SafetyCenterStaticEntryGroup.CREATOR)
}
@Test
- fun equals_hashCode_toString_equalByValue_areEqual() {
- val group = SafetyCenterStaticEntryGroup("a title", listOf(staticEntry1))
- val equivalentGroup = SafetyCenterStaticEntryGroup("a title", listOf(staticEntry1))
-
- assertThat(group).isEqualTo(equivalentGroup)
- assertThat(group.hashCode()).isEqualTo(equivalentGroup.hashCode())
- assertThat(group.toString()).isEqualTo(equivalentGroup.toString())
- }
-
- @Test
- fun equals_toString_withDifferentTitles_areNotEqual() {
- val group = SafetyCenterStaticEntryGroup("a title", listOf(staticEntry1))
- val differentGroup = SafetyCenterStaticEntryGroup("a different title", listOf(staticEntry1))
-
- assertThat(group).isNotEqualTo(differentGroup)
- assertThat(group.toString()).isNotEqualTo(differentGroup.toString())
- }
-
- @Test
- fun equals_toString_withDifferentStaticEntries_areNotEqual() {
- val group = SafetyCenterStaticEntryGroup("a title", listOf(staticEntry1))
- val differentGroup = SafetyCenterStaticEntryGroup("a different title", listOf(staticEntry2))
-
- assertThat(group).isNotEqualTo(differentGroup)
- assertThat(group.toString()).isNotEqualTo(differentGroup.toString())
+ fun equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
+ EqualsHashCodeToStringTester()
+ .addEqualityGroup(
+ staticEntryGroup,
+ SafetyCenterStaticEntryGroup("a title", listOf(staticEntry1, staticEntry2))
+ )
+ .addEqualityGroup(
+ SafetyCenterStaticEntryGroup("a title", listOf(staticEntry1)),
+ SafetyCenterStaticEntryGroup("a title", listOf(staticEntry1))
+ )
+ .addEqualityGroup(
+ SafetyCenterStaticEntryGroup("a different title", listOf(staticEntry1)))
+ .addEqualityGroup(SafetyCenterStaticEntryGroup("a title", listOf(staticEntry2)))
+ .test()
}
-} \ No newline at end of file
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterStaticEntryTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterStaticEntryTest.kt
index 8902aebfd..0e79a9d2a 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterStaticEntryTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterStaticEntryTest.kt
@@ -20,10 +20,11 @@ import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
import android.safetycenter.SafetyCenterStaticEntry
+import android.safetycenter.cts.testing.EqualsHashCodeToStringTester
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.ext.truth.os.ParcelableSubject.assertThat
import androidx.test.filters.SdkSuppress
import com.google.common.truth.Truth.assertThat
import org.junit.Test
@@ -34,16 +35,15 @@ import org.junit.runner.RunWith
class SafetyCenterStaticEntryTest {
private val context: Context = ApplicationProvider.getApplicationContext()
- private val pendingIntent1 = PendingIntent.getActivity(
+ private val pendingIntent1 =
+ PendingIntent.getActivity(context, 0, Intent("Fake Data"), PendingIntent.FLAG_IMMUTABLE)
+ private val pendingIntent2 =
+ PendingIntent.getActivity(
context,
- /* requestCode= */ 0,
- Intent("Fake Data"),
- PendingIntent.FLAG_IMMUTABLE)
- private val pendingIntent2 = PendingIntent.getActivity(
- context,
- /* requestCode= */ 0,
+ 0,
Intent("Fake Different Data"),
- PendingIntent.FLAG_IMMUTABLE)
+ PendingIntent.FLAG_IMMUTABLE
+ )
private val title1 = "a title"
private val title2 = "another title"
@@ -51,8 +51,17 @@ class SafetyCenterStaticEntryTest {
private val summary1 = "a summary"
private val summary2 = "another summary"
- private val staticEntry1 = SafetyCenterStaticEntry(title1, summary1, pendingIntent1)
- private val staticEntry2 = SafetyCenterStaticEntry(title2, summary2, pendingIntent2)
+ private val staticEntry1 =
+ SafetyCenterStaticEntry.Builder(title1)
+ .setSummary(summary1)
+ .setPendingIntent(pendingIntent1)
+ .build()
+ private val staticEntry2 =
+ SafetyCenterStaticEntry.Builder(title2)
+ .setSummary(summary2)
+ .setPendingIntent(pendingIntent2)
+ .build()
+ private val staticEntryMinimal = SafetyCenterStaticEntry.Builder("").build()
@Test
fun getTitle_returnsTitle() {
@@ -64,75 +73,72 @@ class SafetyCenterStaticEntryTest {
fun getSummary_returnsSummary() {
assertThat(staticEntry1.summary).isEqualTo(summary1)
assertThat(staticEntry2.summary).isEqualTo(summary2)
- assertThat(SafetyCenterStaticEntry("", null, pendingIntent1).summary).isNull()
+ assertThat(staticEntryMinimal.summary).isNull()
}
@Test
fun getPendingIntent_returnsPendingIntent() {
assertThat(staticEntry1.pendingIntent).isEqualTo(pendingIntent1)
assertThat(staticEntry2.pendingIntent).isEqualTo(pendingIntent2)
+ assertThat(staticEntryMinimal.pendingIntent).isNull()
}
@Test
fun describeContents_returns0() {
assertThat(staticEntry1.describeContents()).isEqualTo(0)
+ assertThat(staticEntry2.describeContents()).isEqualTo(0)
+ assertThat(staticEntryMinimal.describeContents()).isEqualTo(0)
}
@Test
- fun createFromParcel_withWriteToParcel_returnsEquivalentObject() {
- val parcel: Parcel = Parcel.obtain()
-
- staticEntry1.writeToParcel(parcel, 0 /* flags */)
- parcel.setDataPosition(0)
- val fromParcel = SafetyCenterStaticEntry.CREATOR.createFromParcel(parcel)
- parcel.recycle()
-
- assertThat(fromParcel).isEqualTo(staticEntry1)
- }
-
- @Test
- fun equals_hashCode_toString_equalByReference_areEqual() {
- assertThat(staticEntry1).isEqualTo(staticEntry1)
- assertThat(staticEntry1.hashCode()).isEqualTo(staticEntry1.hashCode())
- assertThat(staticEntry1.toString()).isEqualTo(staticEntry1.toString())
- }
-
- @Test
- fun equals_hashCode_toString_equalByValue_areEqual() {
- val staticEntry = SafetyCenterStaticEntry("titlee", "sumaree", pendingIntent1)
- val equivalentStaticEntry = SafetyCenterStaticEntry("titlee", "sumaree", pendingIntent1)
-
- assertThat(staticEntry).isEqualTo(equivalentStaticEntry)
- assertThat(staticEntry.hashCode()).isEqualTo(equivalentStaticEntry.hashCode())
- assertThat(staticEntry.toString()).isEqualTo(equivalentStaticEntry.toString())
+ fun parcelRoundTrip_recreatesEqual() {
+ assertThat(staticEntry1).recreatesEqual(SafetyCenterStaticEntry.CREATOR)
+ assertThat(staticEntry2).recreatesEqual(SafetyCenterStaticEntry.CREATOR)
+ assertThat(staticEntryMinimal).recreatesEqual(SafetyCenterStaticEntry.CREATOR)
}
@Test
- fun equals_toString_withDifferentTitles_areNotEqual() {
- val staticEntry = SafetyCenterStaticEntry("a title", "a summary", pendingIntent1)
- val differentStaticEntry =
- SafetyCenterStaticEntry("a different title", "a summary", pendingIntent1)
-
- assertThat(staticEntry).isNotEqualTo(differentStaticEntry)
- assertThat(staticEntry.toString()).isNotEqualTo(differentStaticEntry.toString())
- }
-
- @Test
- fun equals_toString_withDifferentSummaries_areNotEqual() {
- val staticEntry = SafetyCenterStaticEntry("a title", "a summary", pendingIntent1)
- val differentStaticEntry =
- SafetyCenterStaticEntry("a title", "a different summary", pendingIntent1)
-
- assertThat(staticEntry).isNotEqualTo(differentStaticEntry)
- assertThat(staticEntry.toString()).isNotEqualTo(differentStaticEntry.toString())
- }
-
- @Test
- fun equals_toString_withDifferentPendingIntents_areNotEqual() {
- val staticEntry = SafetyCenterStaticEntry("a title", "a summary", pendingIntent1)
- val differentStaticEntry = SafetyCenterStaticEntry("a title", "a summary", pendingIntent2)
-
- assertThat(staticEntry).isNotEqualTo(differentStaticEntry)
- assertThat(staticEntry.toString()).isNotEqualTo(differentStaticEntry.toString())
+ fun equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
+ EqualsHashCodeToStringTester()
+ .addEqualityGroup(
+ staticEntry1,
+ SafetyCenterStaticEntry.Builder("a title")
+ .setSummary("a summary")
+ .setPendingIntent(pendingIntent1)
+ .build(),
+ SafetyCenterStaticEntry.Builder(staticEntry1).build()
+ )
+ .addEqualityGroup(staticEntry2)
+ .addEqualityGroup(staticEntryMinimal,
+ SafetyCenterStaticEntry.Builder("").build())
+ .addEqualityGroup(
+ SafetyCenterStaticEntry.Builder("titlee")
+ .setSummary("sumaree")
+ .setPendingIntent(pendingIntent1)
+ .build(),
+ SafetyCenterStaticEntry.Builder("titlee")
+ .setSummary("sumaree")
+ .setPendingIntent(pendingIntent1)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetyCenterStaticEntry.Builder("a different title")
+ .setSummary("a summary")
+ .setPendingIntent(pendingIntent1)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetyCenterStaticEntry.Builder("a title")
+ .setSummary("a different summary")
+ .setPendingIntent(pendingIntent1)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetyCenterStaticEntry.Builder("a title")
+ .setSummary("a summary")
+ .setPendingIntent(pendingIntent2)
+ .build()
+ )
+ .test()
}
-} \ No newline at end of file
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterStatusTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterStatusTest.kt
index 68edbf39e..cb6d1936b 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterStatusTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterStatusTest.kt
@@ -17,9 +17,10 @@
package android.safetycenter.cts
import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
import android.safetycenter.SafetyCenterStatus
+import android.safetycenter.cts.testing.EqualsHashCodeToStringTester
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.ext.truth.os.ParcelableSubject.assertThat
import androidx.test.filters.SdkSuppress
import com.google.common.truth.Truth.assertThat
import org.junit.Test
@@ -29,9 +30,8 @@ import org.junit.runner.RunWith
@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
class SafetyCenterStatusTest {
- val baseStatus = SafetyCenterStatus.Builder()
- .setTitle("This is my title")
- .setSummary("This is my summary")
+ private val baseStatus =
+ SafetyCenterStatus.Builder("This is my title", "This is my summary")
.setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_RECOMMENDATION)
.setRefreshStatus(SafetyCenterStatus.REFRESH_STATUS_DATA_FETCH_IN_PROGRESS)
.build()
@@ -39,80 +39,84 @@ class SafetyCenterStatusTest {
@Test
fun getTitle_returnsTitle() {
assertThat(SafetyCenterStatus.Builder(baseStatus).setTitle("title").build().title)
- .isEqualTo("title")
+ .isEqualTo("title")
assertThat(SafetyCenterStatus.Builder(baseStatus).setTitle("different title").build().title)
- .isEqualTo("different title")
+ .isEqualTo("different title")
}
@Test
fun getSummary_returnsSummary() {
assertThat(SafetyCenterStatus.Builder(baseStatus).setSummary("summary").build().summary)
- .isEqualTo("summary")
+ .isEqualTo("summary")
assertThat(
- SafetyCenterStatus.Builder(baseStatus)
- .setSummary("different summary")
- .build()
- .summary)
- .isEqualTo("different summary")
+ SafetyCenterStatus.Builder(baseStatus).setSummary("different summary").build().summary
+ )
+ .isEqualTo("different summary")
}
@Test
fun getSeverityLevel_returnsSeverityLevel() {
assertThat(
- SafetyCenterStatus.Builder(baseStatus)
- .setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK)
- .build()
- .severityLevel)
- .isEqualTo(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK)
+ SafetyCenterStatus.Builder(baseStatus)
+ .setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK)
+ .build()
+ .severityLevel
+ )
+ .isEqualTo(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK)
assertThat(
- SafetyCenterStatus.Builder(baseStatus)
- .setSeverityLevel(
- SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING)
- .build()
- .severityLevel)
- .isEqualTo(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING)
+ SafetyCenterStatus.Builder(baseStatus)
+ .setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING)
+ .build()
+ .severityLevel
+ )
+ .isEqualTo(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING)
}
@Test
fun getSeverityLevel_defaultUnknown() {
assertThat(
- SafetyCenterStatus.Builder()
- .setTitle("This is my title")
- .setSummary("This is my summary")
- .build()
- .severityLevel)
- .isEqualTo(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_UNKNOWN)
+ SafetyCenterStatus.Builder(
+ "This is my title",
+ "This is my summary"
+ )
+ .setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_UNKNOWN)
+ .build()
+ .severityLevel
+ )
+ .isEqualTo(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_UNKNOWN)
}
@Test
fun getRefreshStatus_returnsRefreshStatus() {
assertThat(
- SafetyCenterStatus.Builder(baseStatus)
- .setRefreshStatus(SafetyCenterStatus.REFRESH_STATUS_NONE)
- .build()
- .refreshStatus)
- .isEqualTo(SafetyCenterStatus.REFRESH_STATUS_NONE)
+ SafetyCenterStatus.Builder(baseStatus)
+ .setRefreshStatus(SafetyCenterStatus.REFRESH_STATUS_NONE)
+ .build()
+ .refreshStatus
+ )
+ .isEqualTo(SafetyCenterStatus.REFRESH_STATUS_NONE)
assertThat(
- SafetyCenterStatus.Builder(baseStatus)
- .setRefreshStatus(SafetyCenterStatus.REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS)
- .build()
- .refreshStatus)
- .isEqualTo(SafetyCenterStatus.REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS)
+ SafetyCenterStatus.Builder(baseStatus)
+ .setRefreshStatus(SafetyCenterStatus.REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS)
+ .build()
+ .refreshStatus
+ )
+ .isEqualTo(SafetyCenterStatus.REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS)
}
@Test
fun getRefreshStatus_defaultNone() {
assertThat(
- SafetyCenterStatus.Builder()
- .setTitle("This is my title")
- .setSummary("This is my summary")
- .build()
- .refreshStatus)
- .isEqualTo(SafetyCenterStatus.REFRESH_STATUS_NONE)
+ SafetyCenterStatus.Builder("This is my title", "This is my summary")
+ .setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_UNKNOWN)
+ .build()
+ .refreshStatus
+ )
+ .isEqualTo(SafetyCenterStatus.REFRESH_STATUS_NONE)
}
@Test
@@ -121,87 +125,43 @@ class SafetyCenterStatusTest {
}
@Test
- fun createFromParcel_withWriteToParcel_returnsEquivalentObject() {
- val parcel: Parcel = Parcel.obtain()
- baseStatus.writeToParcel(parcel, 0 /* flags */)
- parcel.setDataPosition(0)
- val fromParcel = SafetyCenterStatus.CREATOR.createFromParcel(parcel)
- parcel.recycle()
-
- assertThat(fromParcel).isEqualTo(baseStatus)
+ fun parcelRoundTrip_recreatesEqual() {
+ assertThat(baseStatus).recreatesEqual(SafetyCenterStatus.CREATOR)
}
@Test
- fun equals_hashCode_toString_equalByReference_areEqual() {
- assertThat(baseStatus).isEqualTo(baseStatus)
- assertThat(baseStatus.hashCode()).isEqualTo(baseStatus.hashCode())
- assertThat(baseStatus.toString()).isEqualTo(baseStatus.toString())
- }
-
- @Test
- fun equals_hashCode_toString_equalByValue_areEqual() {
- val status = SafetyCenterStatus.Builder()
- .setTitle("same title")
- .setSummary("same summary")
- .setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK)
- .build()
- val equivalentStatus = SafetyCenterStatus.Builder()
- .setTitle("same title")
- .setSummary("same summary")
- .setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK)
- .build()
-
- assertThat(status).isEqualTo(equivalentStatus)
- assertThat(status.hashCode()).isEqualTo(equivalentStatus.hashCode())
- assertThat(status.toString()).isEqualTo(equivalentStatus.toString())
- }
-
- @Test
- fun equals_hashCode_toString_fromCopyBuilder_areEqual() {
- val copyOfBaseStatus = SafetyCenterStatus.Builder(baseStatus).build()
-
- assertThat(copyOfBaseStatus).isEqualTo(baseStatus)
- assertThat(copyOfBaseStatus.hashCode()).isEqualTo(baseStatus.hashCode())
- assertThat(copyOfBaseStatus.toString()).isEqualTo(baseStatus.toString())
- }
-
- @Test
- fun equals_toString_withDifferentTitles_areNotEqual() {
- val unequalStatus = SafetyCenterStatus.Builder(baseStatus)
- .setTitle("that's discarsting")
- .build()
-
- assertThat(unequalStatus).isNotEqualTo(baseStatus)
- assertThat(unequalStatus.toString()).isNotEqualTo(baseStatus.toString())
- }
-
- @Test
- fun equals_toString_withDifferentSummaries_areNotEqual() {
- val unequalStatus = SafetyCenterStatus.Builder(baseStatus)
- .setSummary("discarsting sheet")
- .build()
-
- assertThat(unequalStatus).isNotEqualTo(baseStatus)
- assertThat(unequalStatus.toString()).isNotEqualTo(baseStatus.toString())
- }
-
- @Test
- fun equals_toString_withDifferentSeverityLevels_arNotEqual() {
- val unequalStatus = SafetyCenterStatus.Builder(baseStatus)
- .setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK)
- .build()
-
- assertThat(unequalStatus).isNotEqualTo(baseStatus)
- assertThat(unequalStatus.toString()).isNotEqualTo(baseStatus.toString())
- }
-
- @Test
- fun equals_toString_withDifferentRefreshStatuses_areNotEqual() {
- val unequalStatus = SafetyCenterStatus.Builder(baseStatus)
- .setRefreshStatus(SafetyCenterStatus.REFRESH_STATUS_NONE)
- .build()
-
- assertThat(unequalStatus).isNotEqualTo(baseStatus)
- assertThat(unequalStatus.toString()).isNotEqualTo(baseStatus.toString())
+ fun equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
+ EqualsHashCodeToStringTester()
+ .addEqualityGroup(
+ baseStatus,
+ SafetyCenterStatus.Builder("This is my title", "This is my summary")
+ .setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_RECOMMENDATION)
+ .setRefreshStatus(SafetyCenterStatus.REFRESH_STATUS_DATA_FETCH_IN_PROGRESS)
+ .build(),
+ SafetyCenterStatus.Builder(baseStatus).build()
+ )
+ .addEqualityGroup(
+ SafetyCenterStatus.Builder("same title", "same summary")
+ .setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK)
+ .build(),
+ SafetyCenterStatus.Builder("same title", "same summary")
+ .setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetyCenterStatus.Builder(baseStatus).setTitle("that's not it").build())
+ .addEqualityGroup(
+ SafetyCenterStatus.Builder(baseStatus).setSummary("that's not it").build())
+ .addEqualityGroup(
+ SafetyCenterStatus.Builder(baseStatus)
+ .setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetyCenterStatus.Builder(baseStatus)
+ .setRefreshStatus(SafetyCenterStatus.REFRESH_STATUS_NONE)
+ .build()
+ )
+ .test()
}
-} \ No newline at end of file
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterUnsupportedTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterUnsupportedTest.kt
index 5265a4fab..f1f9aae5c 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterUnsupportedTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterUnsupportedTest.kt
@@ -19,11 +19,12 @@ package android.safetycenter.cts
import android.content.Context
import android.content.Intent
import android.content.Intent.ACTION_SAFETY_CENTER
+import android.content.pm.PackageManager.FEATURE_AUTOMOTIVE
import android.os.Build.VERSION_CODES.TIRAMISU
import android.safetycenter.SafetyCenterManager
-import android.safetycenter.testing.SafetyCenterFlags
-import android.safetycenter.testing.SafetyCenterFlags.deviceSupportsSafetyCenter
-import android.safetycenter.testing.isSafetyCenterEnabledWithPermission
+import android.safetycenter.cts.testing.SafetyCenterApisWithShellPermissions.isSafetyCenterEnabledWithPermission
+import android.safetycenter.cts.testing.SafetyCenterFlags
+import android.safetycenter.cts.testing.SafetyCenterFlags.deviceSupportsSafetyCenter
import android.support.test.uiautomator.By
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -39,6 +40,7 @@ import org.junit.runner.RunWith
@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
class SafetyCenterUnsupportedTest {
private val context: Context = getApplicationContext()
+ private val packageManager = context.packageManager
private val safetyCenterManager = context.getSystemService(SafetyCenterManager::class.java)!!
@Before
@@ -48,6 +50,9 @@ class SafetyCenterUnsupportedTest {
@Test
fun launchActivity_showsSecurityTitle() {
+ // The security page redirects to the cars settings page on auto devices.
+ assumeFalse(packageManager.hasSystemFeature(FEATURE_AUTOMOTIVE))
+
startSafetyCenterActivity()
// CollapsingToolbar title can't be found by text, so using description instead.
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyEventTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyEventTest.kt
index a13b4e425..1f7ba215b 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyEventTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyEventTest.kt
@@ -22,10 +22,9 @@ import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_DEVICE_REBOOTED
import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_REFRESH_REQUESTED
import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED
import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
-import android.safetycenter.testing.AnyTester.assertThatRepresentationsAreEqual
-import android.safetycenter.testing.AnyTester.assertThatRepresentationsAreNotEqual
-import android.safetycenter.testing.ParcelableTester.assertThatRoundTripReturnsOriginal
+import android.safetycenter.cts.testing.EqualsHashCodeToStringTester
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.ext.truth.os.ParcelableSubject.assertThat
import androidx.test.filters.SdkSuppress
import com.google.common.truth.Truth.assertThat
import org.junit.Test
@@ -84,106 +83,70 @@ class SafetyEventTest {
}
@Test
- fun createFromParcel_withWriteToParcel_returnsOriginalSafetySourceData() {
+ fun parcelRoundTrip_recreatesEqual() {
val safetyEvent =
SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
.setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
.setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
.build()
- assertThatRoundTripReturnsOriginal(safetyEvent, SafetyEvent.CREATOR)
+ assertThat(safetyEvent).recreatesEqual(SafetyEvent.CREATOR)
}
- // TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
@Test
- fun hashCode_equals_toString_withEqualByReference_areEqual() {
- val safetyEvent =
- SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
- .setRefreshBroadcastId(REFRESH_BROADCAST_ID)
- .build()
- val otherSafetyEvent = safetyEvent
-
- assertThatRepresentationsAreEqual(safetyEvent, otherSafetyEvent)
- }
-
- @Test
- fun hashCode_equals_toString_withAllFieldsEqual_areEqual() {
- val safetyEvent =
- SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
- .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
- .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
- .build()
- val otherSafetyEvent =
- SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
- .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
- .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
- .build()
-
- assertThatRepresentationsAreEqual(safetyEvent, otherSafetyEvent)
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentSafetyEventTypes_areNotEqual() {
- val safetyEvent =
- SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
- .build()
- val otherSafetyEvent =
- SafetyEvent.Builder(SAFETY_EVENT_TYPE_DEVICE_REBOOTED)
- .build()
-
- assertThatRepresentationsAreNotEqual(safetyEvent, otherSafetyEvent)
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentRefreshBroadcastIds_areNotEqual() {
- val safetyEvent =
- SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
- .setRefreshBroadcastId(REFRESH_BROADCAST_ID)
- .build()
- val otherSafetyEvent =
- SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
- .setRefreshBroadcastId(OTHER_REFRESH_BROADCAST_ID)
- .build()
-
- assertThatRepresentationsAreNotEqual(safetyEvent, otherSafetyEvent)
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentIssueIds_areNotEqual() {
- val safetyEvent =
- SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
- .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
- .build()
- val otherSafetyEvent =
- SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
- .setSafetySourceIssueId(OTHER_SAFETY_SOURCE_ISSUE_ID)
- .build()
-
- assertThatRepresentationsAreNotEqual(safetyEvent, otherSafetyEvent)
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentActionIds_areNotEqual() {
- val safetyEvent =
- SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
- .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
- .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
- .build()
- val otherSafetyEvent =
- SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
- .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
- .setSafetySourceIssueActionId(OTHER_SAFETY_SOURCE_ISSUE_ACTION_ID)
- .build()
-
- assertThatRepresentationsAreNotEqual(safetyEvent, otherSafetyEvent)
+ fun equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
+ EqualsHashCodeToStringTester()
+ .addEqualityGroup(
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
+ .setRefreshBroadcastId(REFRESH_BROADCAST_ID)
+ .build(),
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
+ .setRefreshBroadcastId(REFRESH_BROADCAST_ID)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+ .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
+ .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
+ .build(),
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+ .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
+ .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
+ .build()
+ )
+ .addEqualityGroup(SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED).build())
+ .addEqualityGroup(SafetyEvent.Builder(SAFETY_EVENT_TYPE_DEVICE_REBOOTED).build())
+ .addEqualityGroup(
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
+ .setRefreshBroadcastId(OTHER_REFRESH_BROADCAST_ID)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+ .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+ .setSafetySourceIssueId(OTHER_SAFETY_SOURCE_ISSUE_ID)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+ .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
+ .setSafetySourceIssueActionId(OTHER_SAFETY_SOURCE_ISSUE_ACTION_ID)
+ .build()
+ )
+ .test()
}
companion object {
- const val REFRESH_BROADCAST_ID = "refresh_broadcast_id"
- const val OTHER_REFRESH_BROADCAST_ID = "other_refresh_broadcast_id"
- const val SAFETY_SOURCE_ISSUE_ID = "safety_source_issue_id"
- const val OTHER_SAFETY_SOURCE_ISSUE_ID = "other_safety_source_issue_id"
- const val SAFETY_SOURCE_ISSUE_ACTION_ID = "safety_source_issue_action_id"
- const val OTHER_SAFETY_SOURCE_ISSUE_ACTION_ID = "other_safety_source_issue_action_id"
+ private const val REFRESH_BROADCAST_ID = "refresh_broadcast_id"
+ private const val OTHER_REFRESH_BROADCAST_ID = "other_refresh_broadcast_id"
+ private const val SAFETY_SOURCE_ISSUE_ID = "safety_source_issue_id"
+ private const val OTHER_SAFETY_SOURCE_ISSUE_ID = "other_safety_source_issue_id"
+ private const val SAFETY_SOURCE_ISSUE_ACTION_ID = "safety_source_issue_action_id"
+ private const val OTHER_SAFETY_SOURCE_ISSUE_ACTION_ID =
+ "other_safety_source_issue_action_id"
}
-} \ No newline at end of file
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceDataTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceDataTest.kt
index 76090bf3c..6e9330674 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceDataTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceDataTest.kt
@@ -21,18 +21,22 @@ import android.app.PendingIntent.FLAG_IMMUTABLE
import android.content.Context
import android.content.Intent
import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
import android.safetycenter.SafetySourceData
+import android.safetycenter.SafetySourceData.SEVERITY_LEVEL_CRITICAL_WARNING
+import android.safetycenter.SafetySourceData.SEVERITY_LEVEL_INFORMATION
+import android.safetycenter.SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION
+import android.safetycenter.SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED
import android.safetycenter.SafetySourceIssue
-import android.safetycenter.SafetySourceIssue.ISSUE_CATEGORY_ACCOUNT
import android.safetycenter.SafetySourceStatus
-import android.safetycenter.SafetySourceStatus.IconAction.ICON_TYPE_GEAR
+import android.safetycenter.cts.testing.EqualsHashCodeToStringTester
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.ext.truth.os.ParcelableSubject.assertThat
import androidx.test.filters.SdkSuppress
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
+import kotlin.test.assertFailsWith
/** CTS tests for [SafetySourceData]. */
@RunWith(AndroidJUnit4::class)
@@ -40,107 +44,54 @@ import org.junit.runner.RunWith
class SafetySourceDataTest {
private val context: Context = getApplicationContext()
- private val status1 = SafetySourceStatus.Builder(
- "Status title 1",
- "Status summary 1",
- SafetySourceStatus.STATUS_LEVEL_NONE,
- PendingIntent.getActivity(context, 0 /* requestCode= */,
- Intent("Status PendingIntent 1"), FLAG_IMMUTABLE))
- .setEnabled(false)
- .build()
- private val status2 = SafetySourceStatus.Builder(
- "Status title 2",
- "Status summary 2",
- SafetySourceStatus.STATUS_LEVEL_RECOMMENDATION,
- PendingIntent.getActivity(context, 0 /* requestCode= */,
- Intent("Status PendingIntent 2"), FLAG_IMMUTABLE))
- .setIconAction(SafetySourceStatus.IconAction(ICON_TYPE_GEAR,
- PendingIntent.getActivity(context, 0 /* requestCode= */,
- Intent("IconAction PendingIntent 2"), FLAG_IMMUTABLE)))
- .build()
- private val issue1 = SafetySourceIssue.Builder(
- "Issue id 1",
- "Issue summary 1",
- "Issue summary 1",
- SafetySourceIssue.SEVERITY_LEVEL_INFORMATION, "issue_type_id"
- )
- .setSubtitle("Issue subtitle 1")
- .setIssueCategory(ISSUE_CATEGORY_ACCOUNT)
- .addAction(
- SafetySourceIssue.Action.Builder(
- "action_id_1",
- "Action label 1",
- PendingIntent.getActivity(
- context, 0 /* requestCode= */,
- Intent("Issue PendingIntent 1"), FLAG_IMMUTABLE
- )
- )
- .build()
- )
- .build()
- private val issue2 = SafetySourceIssue.Builder(
- "Issue id 2",
- "Issue title 2",
- "Issue summary 2",
- SafetySourceIssue.SEVERITY_LEVEL_RECOMMENDATION, "issue_type_id"
- )
- .addAction(
- SafetySourceIssue.Action.Builder(
- "action_id_2",
- "Action label 2",
- PendingIntent.getService(
- context, 0 /* requestCode= */,
- Intent("Issue PendingIntent 2"), FLAG_IMMUTABLE
- )
- ).build()
- )
- .setOnDismissPendingIntent(
- PendingIntent.getService(
- context,
- 0 /* requestCode= */,
- Intent("Issue OnDismissPendingIntent 2"), FLAG_IMMUTABLE
- )
- )
- .build()
-
@Test
fun getStatus_withDefaultBuilder_returnsNull() {
- val safetySourceData = SafetySourceData.Builder().build()
+ val safetySourceData = SafetySourceData.Builder()
+ .addIssue(createIssue(SEVERITY_LEVEL_INFORMATION))
+ .build()
assertThat(safetySourceData.status).isNull()
}
@Test
fun getStatus_whenSetExplicitly_returnsStatus() {
+ val status = createStatus(SEVERITY_LEVEL_INFORMATION)
val safetySourceData = SafetySourceData.Builder()
- .setStatus(status1)
- .build()
+ .setStatus(status)
+ .build()
- assertThat(safetySourceData.status).isEqualTo(status1)
+ assertThat(safetySourceData.status).isEqualTo(status)
}
@Test
fun getIssues_withDefaultBuilder_returnsEmptyList() {
- val safetySourceData = SafetySourceData.Builder().build()
+ val safetySourceData = SafetySourceData.Builder()
+ .setStatus(createStatus(SEVERITY_LEVEL_INFORMATION))
+ .build()
assertThat(safetySourceData.issues).isEmpty()
}
@Test
fun getIssues_whenSetExplicitly_returnsIssues() {
+ val firstIssue = createIssue(SEVERITY_LEVEL_INFORMATION, 1)
+ val secondIssue = createIssue(SEVERITY_LEVEL_INFORMATION, 2)
val safetySourceData = SafetySourceData.Builder()
- .addIssue(issue1)
- .addIssue(issue2)
- .build()
+ .addIssue(firstIssue)
+ .addIssue(secondIssue)
+ .build()
- assertThat(safetySourceData.issues).containsExactly(issue1, issue2).inOrder()
+ assertThat(safetySourceData.issues).containsExactly(firstIssue, secondIssue).inOrder()
}
@Test
fun clearIssues_removesAllIssues() {
+ val firstIssue = createIssue(SEVERITY_LEVEL_INFORMATION, 1)
+ val secondIssue = createIssue(SEVERITY_LEVEL_INFORMATION, 2)
val safetySourceData = SafetySourceData.Builder()
- .addIssue(issue1)
- .addIssue(issue2)
+ .setStatus(createStatus(SEVERITY_LEVEL_INFORMATION))
+ .addIssue(firstIssue)
+ .addIssue(secondIssue)
.clearIssues()
.build()
@@ -148,149 +99,211 @@ class SafetySourceDataTest {
}
@Test
- fun describeContents_returns0() {
- val safetySourceData = SafetySourceData.Builder()
- .setStatus(status1)
- .addIssue(issue1)
- .addIssue(issue2)
- .build()
+ fun build_withNoStatusAndNoIssues_doesNotThrow() {
+ val builder = SafetySourceData.Builder()
- assertThat(safetySourceData.describeContents()).isEqualTo(0)
+ assertThat(builder.build()).isNotNull()
}
@Test
- fun createFromParcel_withWriteToParcel_returnsOriginalSafetySourceData() {
- val safetySourceData = SafetySourceData.Builder()
- .setStatus(status1)
- .addIssue(issue1)
- .addIssue(issue2)
- .build()
+ fun build_withNoStatusAndInfoIssues_doesNotThrow() {
+ val builder = SafetySourceData.Builder().addIssue(createIssue(SEVERITY_LEVEL_INFORMATION))
- val parcel: Parcel = Parcel.obtain()
- safetySourceData.writeToParcel(parcel, 0 /* flags */)
- parcel.setDataPosition(0)
- val safetySourceDataFromParcel: SafetySourceData =
- SafetySourceData.CREATOR.createFromParcel(parcel)
- parcel.recycle()
+ assertThat(builder.build()).isNotNull()
+ }
- assertThat(safetySourceDataFromParcel).isEqualTo(safetySourceData)
+ @Test
+ fun build_withNoStatusAndRecommendationIssues_doesNotThrow() {
+ val builder = SafetySourceData.Builder()
+ .addIssue(createIssue(SEVERITY_LEVEL_RECOMMENDATION))
+
+ assertThat(builder.build()).isNotNull()
}
- // TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
@Test
- fun hashCode_equals_toString_withEqualByReference_withoutStatusAndIssues_areEqual() {
- val safetySourceData = SafetySourceData.Builder().build()
- val otherSafetySourceData = safetySourceData
+ fun build_withNoStatusAndCriticalIssues_doesNotThrow() {
+ val builder = SafetySourceData.Builder()
+ .addIssue(createIssue(SEVERITY_LEVEL_CRITICAL_WARNING))
- assertThat(safetySourceData.hashCode()).isEqualTo(otherSafetySourceData.hashCode())
- assertThat(safetySourceData).isEqualTo(otherSafetySourceData)
- assertThat(safetySourceData.toString()).isEqualTo(otherSafetySourceData.toString())
+ assertThat(builder.build()).isNotNull()
}
@Test
- fun hashCode_equals_toString_withEqualByReference_withoutIssues_areEqual() {
- val safetySourceData = SafetySourceData.Builder()
- .setStatus(status1)
- .build()
- val otherSafetySourceData = safetySourceData
+ fun build_withUnspecifiedStatusAndNoIssues_doesNotThrow() {
+ val builder = SafetySourceData.Builder().setStatus(createStatus(SEVERITY_LEVEL_UNSPECIFIED))
- assertThat(safetySourceData.hashCode()).isEqualTo(otherSafetySourceData.hashCode())
- assertThat(safetySourceData).isEqualTo(otherSafetySourceData)
- assertThat(safetySourceData.toString()).isEqualTo(otherSafetySourceData.toString())
+ assertThat(builder.build()).isNotNull()
}
@Test
- fun hashCode_equals_toString_withEqualByReference_areEqual() {
- val safetySourceData = SafetySourceData.Builder()
- .setStatus(status1)
- .addIssue(issue1)
- .addIssue(issue2)
- .build()
- val otherSafetySourceData = safetySourceData
+ fun build_withUnspecifiedStatusAndInformationIssues_doesNotThrow() {
+ val builder = SafetySourceData.Builder()
+ .setStatus(createStatus(SEVERITY_LEVEL_UNSPECIFIED))
+ .addIssue(createIssue(SEVERITY_LEVEL_INFORMATION))
- assertThat(safetySourceData.hashCode()).isEqualTo(otherSafetySourceData.hashCode())
- assertThat(safetySourceData).isEqualTo(otherSafetySourceData)
- assertThat(safetySourceData.toString()).isEqualTo(otherSafetySourceData.toString())
+ assertThat(builder.build()).isNotNull()
}
@Test
- fun hashCode_equals_toString_withAllFieldsEqual_areEqual() {
- val safetySourceData = SafetySourceData.Builder()
- .setStatus(status1)
- .addIssue(issue1)
- .addIssue(issue2)
- .build()
- val otherSafetySourceData = SafetySourceData.Builder()
- .setStatus(status1)
- .addIssue(issue1)
- .addIssue(issue2)
- .build()
+ fun build_withInformationStatusAndNoIssues_doesNotThrow() {
+ val builder = SafetySourceData.Builder().setStatus(createStatus(SEVERITY_LEVEL_INFORMATION))
- assertThat(safetySourceData.hashCode()).isEqualTo(otherSafetySourceData.hashCode())
- assertThat(safetySourceData).isEqualTo(otherSafetySourceData)
- assertThat(safetySourceData.toString()).isEqualTo(otherSafetySourceData.toString())
+ assertThat(builder.build()).isNotNull()
}
@Test
- fun hashCode_equals_toString_withDifferentIssues_areNotEqual() {
- val safetySourceData = SafetySourceData.Builder()
- .setStatus(status1)
- .addIssue(issue1)
- .addIssue(issue2)
- .build()
- val otherSafetySourceData = SafetySourceData.Builder()
- .setStatus(status2)
- .addIssue(issue1)
- .addIssue(issue2)
- .build()
+ fun build_withInformationStatusAndInformationIssues_doesNotThrow() {
+ val builder = SafetySourceData.Builder()
+ .setStatus(createStatus(SEVERITY_LEVEL_INFORMATION))
+ .addIssue(createIssue(SEVERITY_LEVEL_INFORMATION))
- assertThat(safetySourceData.hashCode()).isNotEqualTo(otherSafetySourceData.hashCode())
- assertThat(safetySourceData).isNotEqualTo(otherSafetySourceData)
- assertThat(safetySourceData.toString()).isNotEqualTo(otherSafetySourceData.toString())
+ assertThat(builder.build()).isNotNull()
}
@Test
- fun hashCode_equals_toString_withDifferentStatuses_areNotEqual() {
- val safetySourceData = SafetySourceData.Builder()
- .setStatus(status1)
- .addIssue(issue1)
- .addIssue(issue2)
- .build()
- val otherSafetySourceData = SafetySourceData.Builder()
- .setStatus(status1)
- .addIssue(issue1)
- .build()
+ fun build_withInformationStatusAndRecommendationIssues_throwsIllegalArgumentException() {
+ val builder = SafetySourceData.Builder()
+ .setStatus(createStatus(SEVERITY_LEVEL_INFORMATION))
+ .addIssue(createIssue(SEVERITY_LEVEL_RECOMMENDATION))
+
+ val exception = assertFailsWith(IllegalArgumentException::class) {
+ builder.build()
+ }
+ assertThat(exception).hasMessageThat()
+ .isEqualTo(
+ "Safety source data must not contain any issue with a severity level both greater" +
+ " than SEVERITY_LEVEL_INFORMATION and greater than the status severity level"
+ )
+ }
- assertThat(safetySourceData.hashCode()).isNotEqualTo(otherSafetySourceData.hashCode())
- assertThat(safetySourceData).isNotEqualTo(otherSafetySourceData)
- assertThat(safetySourceData.toString()).isNotEqualTo(otherSafetySourceData.toString())
+ @Test
+ fun build_withRecommendationStatusAndNoIssues_doesNotThrow() {
+ val builder = SafetySourceData.Builder()
+ .setStatus(createStatus(SEVERITY_LEVEL_RECOMMENDATION))
+
+ assertThat(builder.build()).isNotNull()
}
@Test
- fun hashCode_equals_toString_withStatusSetInOneAndNotOther_areNotEqual() {
+ fun build_withRecommendationStatusAndInformationIssues_doesNotThrow() {
+ val builder = SafetySourceData.Builder()
+ .setStatus(createStatus(SEVERITY_LEVEL_RECOMMENDATION))
+ .addIssue(createIssue(SEVERITY_LEVEL_INFORMATION))
+
+ assertThat(builder.build()).isNotNull()
+ }
+
+ @Test
+ fun build_withRecommendationStatusAndRecommendationIssues_doesNotThrow() {
+ val builder = SafetySourceData.Builder()
+ .setStatus(createStatus(SEVERITY_LEVEL_RECOMMENDATION))
+ .addIssue(createIssue(SEVERITY_LEVEL_RECOMMENDATION))
+
+ assertThat(builder.build()).isNotNull()
+ }
+
+ @Test
+ fun build_withRecommendationStatusAndCriticalIssues_throwsIllegalArgumentException() {
+ val builder = SafetySourceData.Builder()
+ .setStatus(createStatus(SEVERITY_LEVEL_RECOMMENDATION))
+ .addIssue(createIssue(SEVERITY_LEVEL_CRITICAL_WARNING))
+
+ val exception = assertFailsWith(IllegalArgumentException::class) {
+ builder.build()
+ }
+ assertThat(exception).hasMessageThat()
+ .isEqualTo(
+ "Safety source data must not contain any issue with a severity level both greater" +
+ " than SEVERITY_LEVEL_INFORMATION and greater than the status severity level"
+ )
+ }
+
+ @Test
+ fun describeContents_returns0() {
val safetySourceData = SafetySourceData.Builder()
- .setStatus(status1)
- .build()
- val otherSafetySourceData = SafetySourceData.Builder().build()
+ .setStatus(createStatus(SEVERITY_LEVEL_INFORMATION))
+ .build()
- assertThat(safetySourceData.hashCode()).isNotEqualTo(otherSafetySourceData.hashCode())
- assertThat(safetySourceData).isNotEqualTo(otherSafetySourceData)
- assertThat(safetySourceData.toString()).isNotEqualTo(otherSafetySourceData.toString())
+ assertThat(safetySourceData.describeContents()).isEqualTo(0)
}
@Test
- fun hashCode_equals_toString_withIssuesSetInOneAndNotOther_areNotEqual() {
+ fun parcelRoundTrip_recreatesEqual() {
val safetySourceData = SafetySourceData.Builder()
- .setStatus(status1)
- .addIssue(issue1)
- .addIssue(issue2)
- .build()
- val otherSafetySourceData = SafetySourceData.Builder()
- .setStatus(status1)
- .build()
+ .setStatus(createStatus(SEVERITY_LEVEL_RECOMMENDATION))
+ .addIssue(createIssue(SEVERITY_LEVEL_RECOMMENDATION, 1))
+ .addIssue(createIssue(SEVERITY_LEVEL_INFORMATION, 2))
+ .build()
- assertThat(safetySourceData.hashCode()).isNotEqualTo(otherSafetySourceData.hashCode())
- assertThat(safetySourceData).isNotEqualTo(otherSafetySourceData)
- assertThat(safetySourceData.toString()).isNotEqualTo(otherSafetySourceData.toString())
+ assertThat(safetySourceData).recreatesEqual(SafetySourceData.CREATOR)
}
-} \ No newline at end of file
+
+ @Test
+ fun equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
+ val firstStatus = createStatus(SEVERITY_LEVEL_INFORMATION, 1)
+ val secondStatus = createStatus(SEVERITY_LEVEL_INFORMATION, 2)
+ val firstIssue = createIssue(SEVERITY_LEVEL_INFORMATION, 1)
+ val secondIssue = createIssue(SEVERITY_LEVEL_INFORMATION, 2)
+ EqualsHashCodeToStringTester()
+ .addEqualityGroup(
+ SafetySourceData.Builder().setStatus(firstStatus).build(),
+ SafetySourceData.Builder().setStatus(firstStatus).build()
+ )
+ .addEqualityGroup(
+ SafetySourceData.Builder().addIssue(firstIssue).addIssue(secondIssue).build(),
+ SafetySourceData.Builder().addIssue(firstIssue).addIssue(secondIssue).build()
+ )
+ .addEqualityGroup(
+ SafetySourceData.Builder()
+ .setStatus(firstStatus).addIssue(firstIssue).addIssue(secondIssue).build(),
+ SafetySourceData.Builder()
+ .setStatus(firstStatus).addIssue(firstIssue).addIssue(secondIssue).build()
+ )
+ .addEqualityGroup(SafetySourceData.Builder().setStatus(secondStatus).build())
+ .addEqualityGroup(
+ SafetySourceData.Builder().addIssue(secondIssue).addIssue(firstIssue).build())
+ .addEqualityGroup(SafetySourceData.Builder().addIssue(firstIssue).build())
+ .addEqualityGroup(
+ SafetySourceData.Builder()
+ .setStatus(secondStatus).addIssue(firstIssue).addIssue(secondIssue).build()
+ )
+ .test()
+ }
+
+ private fun createStatus(severityLevel: Int, id: Int = 0) = SafetySourceStatus.Builder(
+ "Status title $id",
+ "Status summary $id",
+ severityLevel
+ )
+ .setPendingIntent(
+ PendingIntent.getActivity(
+ context,
+ 0 /* requestCode= */,
+ Intent("Status PendingIntent $id"),
+ FLAG_IMMUTABLE
+ )
+ )
+ .build()
+
+ private fun createIssue(severityLevel: Int, id: Int = 0) = SafetySourceIssue.Builder(
+ "Issue id $id",
+ "Issue summary $id",
+ "Issue summary $id",
+ severityLevel,
+ "Issue type id $id"
+ )
+ .addAction(
+ SafetySourceIssue.Action.Builder(
+ "Action id $id",
+ "Action label $id",
+ PendingIntent.getActivity(
+ context,
+ 0 /* requestCode= */,
+ Intent("Issue PendingIntent $id"),
+ FLAG_IMMUTABLE
+ )
+ )
+ .build()
+ )
+ .build()
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceErrorDetailsTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceErrorDetailsTest.kt
index ed9136f04..4d9ae4952 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceErrorDetailsTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceErrorDetailsTest.kt
@@ -19,10 +19,9 @@ package android.safetycenter.cts
import android.os.Build
import android.safetycenter.SafetyEvent
import android.safetycenter.SafetySourceErrorDetails
-import android.safetycenter.testing.AnyTester.assertThatRepresentationsAreEqual
-import android.safetycenter.testing.AnyTester.assertThatRepresentationsAreNotEqual
-import android.safetycenter.testing.ParcelableTester.assertThatRoundTripReturnsOriginal
+import android.safetycenter.cts.testing.EqualsHashCodeToStringTester
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.ext.truth.os.ParcelableSubject.assertThat
import androidx.test.filters.SdkSuppress
import com.google.common.truth.Truth.assertThat
import org.junit.Test
@@ -40,39 +39,31 @@ class SafetySourceErrorDetailsTest {
}
@Test
- fun createFromParcel_withWriteToParcel_returnsEquivalentObject() {
+ fun parcelRoundTrip_recreatesEqual() {
val errorDetails = SafetySourceErrorDetails(SAFETY_EVENT)
- assertThatRoundTripReturnsOriginal(errorDetails, SafetySourceErrorDetails.CREATOR)
+ assertThat(errorDetails).recreatesEqual(SafetySourceErrorDetails.CREATOR)
}
@Test
- fun equals_hashCode_toString_equalByReference_areEqual() {
- val errorDetails = SafetySourceErrorDetails(SAFETY_EVENT)
-
- assertThatRepresentationsAreEqual(errorDetails, errorDetails)
- }
-
- @Test
- fun equals_hashCode_toString_equalByValue_areEqual() {
- val errorDetails = SafetySourceErrorDetails(SAFETY_EVENT)
- val equivalentSafetySourceErrorDetails = SafetySourceErrorDetails(SAFETY_EVENT)
-
- assertThatRepresentationsAreEqual(errorDetails, equivalentSafetySourceErrorDetails)
- }
-
- @Test
- fun equals_toString_withDifferentSafetyEvents_areNotEqual() {
- val errorDetails = SafetySourceErrorDetails(
- SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build())
- val otherErrorDetails = SafetySourceErrorDetails(
- SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_DEVICE_REBOOTED).build())
-
- assertThatRepresentationsAreNotEqual(errorDetails, otherErrorDetails)
+ fun equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
+ EqualsHashCodeToStringTester()
+ .addEqualityGroup(
+ SafetySourceErrorDetails(SAFETY_EVENT),
+ SafetySourceErrorDetails(
+ SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build()
+ )
+ )
+ .addEqualityGroup(
+ SafetySourceErrorDetails(
+ SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_DEVICE_REBOOTED).build()
+ )
+ )
+ .test()
}
companion object {
private val SAFETY_EVENT =
SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build()
}
-} \ No newline at end of file
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceIssueTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceIssueTest.kt
index 890e6902c..064be0b5a 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceIssueTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceIssueTest.kt
@@ -21,21 +21,24 @@ import android.app.PendingIntent.FLAG_IMMUTABLE
import android.content.Context
import android.content.Intent
import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
+import android.safetycenter.SafetySourceData.SEVERITY_LEVEL_CRITICAL_WARNING
+import android.safetycenter.SafetySourceData.SEVERITY_LEVEL_INFORMATION
+import android.safetycenter.SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED
import android.safetycenter.SafetySourceIssue
+import android.safetycenter.SafetySourceIssue.Action
import android.safetycenter.SafetySourceIssue.ISSUE_CATEGORY_ACCOUNT
import android.safetycenter.SafetySourceIssue.ISSUE_CATEGORY_DEVICE
import android.safetycenter.SafetySourceIssue.ISSUE_CATEGORY_GENERAL
-import android.safetycenter.SafetySourceIssue.Action
-import android.safetycenter.SafetySourceIssue.SEVERITY_LEVEL_CRITICAL_WARNING
-import android.safetycenter.SafetySourceIssue.SEVERITY_LEVEL_INFORMATION
+import android.safetycenter.cts.testing.EqualsHashCodeToStringTester
+import android.safetycenter.cts.testing.Generic
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.ext.truth.os.ParcelableSubject.assertThat
import androidx.test.filters.SdkSuppress
import com.google.common.truth.Truth.assertThat
-import kotlin.test.assertFailsWith
import org.junit.Test
import org.junit.runner.RunWith
+import kotlin.test.assertFailsWith
/** CTS tests for [SafetySourceIssue]. */
@RunWith(AndroidJUnit4::class)
@@ -43,17 +46,15 @@ import org.junit.runner.RunWith
class SafetySourceIssueTest {
private val context: Context = getApplicationContext()
- private val pendingIntent1: PendingIntent = PendingIntent.getActivity(
- context,
- 0 /* requestCode= */, Intent("PendingIntent 1"), FLAG_IMMUTABLE
- )
+ private val pendingIntent1: PendingIntent =
+ PendingIntent.getActivity(context, 0, Intent("PendingIntent 1"), FLAG_IMMUTABLE)
private val action1 = Action.Builder("action_id_1", "Action label 1", pendingIntent1).build()
- private val pendingIntent2: PendingIntent = PendingIntent.getActivity(
- context,
- 0 /* requestCode= */, Intent("PendingIntent 2"), FLAG_IMMUTABLE
- )
+ private val pendingIntent2: PendingIntent =
+ PendingIntent.getActivity(context, 0, Intent("PendingIntent 2"), FLAG_IMMUTABLE)
private val action2 = Action.Builder("action_id_2", "Action label 2", pendingIntent2).build()
private val action3 = Action.Builder("action_id_3", "Action label 3", pendingIntent1).build()
+ private val pendingIntentService =
+ PendingIntent.getService(context, 0, Intent("PendingIntent service"), FLAG_IMMUTABLE)
@Test
fun action_getId_returnsId() {
@@ -78,9 +79,8 @@ class SafetySourceIssueTest {
@Test
fun action_willResolve_whenSetExplicitly_returnsWillResolve() {
- val action = Action.Builder("action_id", "Action label", pendingIntent1)
- .setWillResolve(true)
- .build()
+ val action =
+ Action.Builder("action_id", "Action label", pendingIntent1).setWillResolve(true).build()
assertThat(action.willResolve()).isTrue()
}
@@ -101,338 +101,431 @@ class SafetySourceIssueTest {
@Test
fun action_getSuccessMessage_whenSetExplicitly_returnsSuccessMessage() {
- val action = Action.Builder("action_id", "Action label", pendingIntent1)
- .setSuccessMessage("Action successfully completed")
- .build()
+ val action =
+ Action.Builder("action_id", "Action label", pendingIntent1)
+ .setSuccessMessage("Action successfully completed")
+ .build()
assertThat(action.successMessage).isEqualTo("Action successfully completed")
}
@Test
- fun action_describeContents_returns0() {
- val action = Action.Builder("action_id", "Action label", pendingIntent1).build()
-
- assertThat(action.describeContents()).isEqualTo(0)
- }
-
- @Test
- fun action_createFromParcel_withWriteToParcel_returnsOriginalAction() {
- val action = Action.Builder("action_id", "Action label", pendingIntent1)
- .setSuccessMessage("Action successfully completed")
- .build()
-
- val parcel: Parcel = Parcel.obtain()
- action.writeToParcel(parcel, 0 /* flags */)
- parcel.setDataPosition(0)
- val actionFromParcel: Action = Action.CREATOR.createFromParcel(parcel)
- parcel.recycle()
-
- assertThat(actionFromParcel).isEqualTo(action)
- }
-
- // TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
- @Test
- fun action_hashCode_equals_toString_withEqualByReferenceActions_areEqual() {
- val action = Action.Builder("action_id", "Action label", pendingIntent1).build()
- val otherAction = action
-
- assertThat(action.hashCode()).isEqualTo(otherAction.hashCode())
- assertThat(action).isEqualTo(otherAction)
- assertThat(action.toString()).isEqualTo(otherAction.toString())
+ fun action_build_withNullId_throwsNullPointerException() {
+ assertFailsWith(NullPointerException::class) {
+ Action.Builder(Generic.asNull(), "Action label", pendingIntent1)
+ }
}
@Test
- fun action_hashCode_equals_toString_withAllFieldsEqual_areEqual() {
- val action = Action.Builder("action_id", "Action label", pendingIntent1).build()
- val otherAction = Action.Builder("action_id", "Action label", pendingIntent1).build()
-
- assertThat(action.hashCode()).isEqualTo(otherAction.hashCode())
- assertThat(action).isEqualTo(otherAction)
- assertThat(action.toString()).isEqualTo(otherAction.toString())
+ fun action_build_withNullLabel_throwsNullPointerException() {
+ assertFailsWith(NullPointerException::class) {
+ Action.Builder("action_id", Generic.asNull(), pendingIntent1)
+ }
}
@Test
- fun action_hashCode_equals_toString_withDifferentIds_areNotEqual() {
- val action = Action.Builder("action_id", "Action label", pendingIntent1).build()
- val otherAction = Action.Builder("other_action_id", "Action label", pendingIntent1).build()
-
- assertThat(action.hashCode()).isNotEqualTo(otherAction.hashCode())
- assertThat(action).isNotEqualTo(otherAction)
- assertThat(action.toString()).isNotEqualTo(otherAction.toString())
+ fun action_build_withNullPendingIntent_throwsNullPointerException() {
+ assertFailsWith(NullPointerException::class) {
+ Action.Builder("action_id", "Action label", Generic.asNull())
+ }
}
@Test
- fun action_hashCode_equals_toString_withDifferentLabels_areNotEqual() {
+ fun action_describeContents_returns0() {
val action = Action.Builder("action_id", "Action label", pendingIntent1).build()
- val otherAction = Action.Builder("action_id", "Other action label", pendingIntent1).build()
- assertThat(action.hashCode()).isNotEqualTo(otherAction.hashCode())
- assertThat(action).isNotEqualTo(otherAction)
- assertThat(action.toString()).isNotEqualTo(otherAction.toString())
+ assertThat(action.describeContents()).isEqualTo(0)
}
@Test
- fun action_hashCode_equals_toString_withDifferentWillResolve_areNotEqual() {
+ fun action_parcelRoundTrip_recreatesEqual() {
val action =
- Action.Builder("action_id", "Action label", pendingIntent1).setWillResolve(false)
+ Action.Builder("action_id", "Action label", pendingIntent1)
+ .setSuccessMessage("Action successfully completed")
.build()
- val otherAction =
- Action.Builder("action_id", "Action label", pendingIntent1).setWillResolve(true).build()
- assertThat(action.hashCode()).isNotEqualTo(otherAction.hashCode())
- assertThat(action).isNotEqualTo(otherAction)
- assertThat(action.toString()).isNotEqualTo(otherAction.toString())
+ assertThat(action).recreatesEqual(Action.CREATOR)
}
@Test
- fun action_hashCode_equals_toString_withDifferentPendingIntents_areNotEqual() {
- val action = Action.Builder(
- "action_id",
- "Action label",
- PendingIntent.getActivity(
- context, 0 /* requestCode= */,
- Intent("Action PendingIntent"), FLAG_IMMUTABLE
+ fun action_equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
+ EqualsHashCodeToStringTester()
+ .addEqualityGroup(
+ Action.Builder("action_id", "Action label", pendingIntent1).build(),
+ Action.Builder("action_id", "Action label", pendingIntent1).build(),
+ Action.Builder("action_id", "Action label", pendingIntent1)
+ .setWillResolve(false)
+ .build()
)
- )
- .build()
- val otherAction = Action.Builder(
- "action_id",
- "Action label",
- PendingIntent.getActivity(
- context, 0 /* requestCode= */,
- Intent("Other action PendingIntent"), FLAG_IMMUTABLE
+ .addEqualityGroup(
+ Action.Builder("action_id", "Action label", pendingIntent1)
+ .setSuccessMessage("Action successfully completed")
+ .build()
)
- )
- .build()
-
- assertThat(action.hashCode()).isNotEqualTo(otherAction.hashCode())
- assertThat(action).isNotEqualTo(otherAction)
- assertThat(action.toString()).isNotEqualTo(otherAction.toString())
- }
-
- @Test
- fun action_hashCode_equals_toString_withDifferentSuccessMessages_areNotEqual() {
- val action =
- Action.Builder("action_id", "Action label", pendingIntent1)
- .setSuccessMessage("Action successfully completed")
- .build()
- val otherAction =
- Action.Builder("action_id", "Action label", pendingIntent1)
- .setSuccessMessage("Other action successfully completed")
- .build()
-
- assertThat(action.hashCode()).isNotEqualTo(otherAction.hashCode())
- assertThat(action).isNotEqualTo(otherAction)
- assertThat(action.toString()).isNotEqualTo(otherAction.toString())
+ .addEqualityGroup(
+ Action.Builder("action_id", "Other action label", pendingIntent1).build())
+ .addEqualityGroup(
+ Action.Builder("other_action_id", "Action label", pendingIntent1).build())
+ .addEqualityGroup(
+ Action.Builder("action_id", "Action label", pendingIntent1)
+ .setWillResolve(true)
+ .build()
+ )
+ .addEqualityGroup(
+ Action.Builder(
+ "action_id",
+ "Action label",
+ PendingIntent.getActivity(
+ context,
+ 0,
+ Intent("Other action PendingIntent"),
+ FLAG_IMMUTABLE
+ )
+ )
+ .build()
+ )
+ .addEqualityGroup(
+ Action.Builder("action_id", "Action label", pendingIntent1)
+ .setSuccessMessage("Other action successfully completed")
+ .build()
+ )
+ .test()
}
@Test
fun getId_returnsId() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- )
- .addAction(action1)
- .build()
+ val safetySourceIssue =
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .addAction(action1)
+ .build()
assertThat(safetySourceIssue.id).isEqualTo("Issue id")
}
@Test
fun getTitle_returnsTitle() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- )
- .addAction(action1)
- .build()
+ val safetySourceIssue =
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .addAction(action1)
+ .build()
assertThat(safetySourceIssue.title).isEqualTo("Issue title")
}
@Test
fun getSubtitle_withDefaultBuilder_returnsNull() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- )
- .addAction(action1)
- .build()
+ val safetySourceIssue =
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .addAction(action1)
+ .build()
assertThat(safetySourceIssue.subtitle).isNull()
}
@Test
fun getSubtitle_whenSetExplicitly_returnsSubtitle() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- )
- .setSubtitle("Issue subtitle")
- .addAction(action1)
- .build()
+ val safetySourceIssue =
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .setSubtitle("Issue subtitle")
+ .addAction(action1)
+ .build()
assertThat(safetySourceIssue.subtitle).isEqualTo("Issue subtitle")
}
@Test
fun getSummary_returnsSummary() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- )
- .addAction(action1)
- .build()
+ val safetySourceIssue =
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .addAction(action1)
+ .build()
assertThat(safetySourceIssue.summary).isEqualTo("Issue summary")
}
@Test
fun getSeverityLevel_returnsSeverityLevel() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).addAction(action1)
- .build()
+ val safetySourceIssue =
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .addAction(action1)
+ .build()
assertThat(safetySourceIssue.severityLevel).isEqualTo(SEVERITY_LEVEL_INFORMATION)
}
@Test
fun getIssueCategory_withDefaultBuilder_returnsGeneralCategory() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).addAction(action1)
- .build()
+ val safetySourceIssue =
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .addAction(action1)
+ .build()
assertThat(safetySourceIssue.issueCategory).isEqualTo(ISSUE_CATEGORY_GENERAL)
}
@Test
fun getIssueCategory_whenSetExplicitly_returnsIssueCategory() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).addAction(action1)
- .setIssueCategory(ISSUE_CATEGORY_DEVICE)
- .build()
+ val safetySourceIssue =
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .addAction(action1)
+ .setIssueCategory(ISSUE_CATEGORY_DEVICE)
+ .build()
assertThat(safetySourceIssue.issueCategory).isEqualTo(ISSUE_CATEGORY_DEVICE)
}
@Test
fun getActions_returnsActions() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).addAction(action1)
- .addAction(action2)
- .build()
+ val safetySourceIssue =
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .addAction(action1)
+ .addAction(action2)
+ .build()
assertThat(safetySourceIssue.actions).containsExactly(action1, action2).inOrder()
}
@Test
fun clearActions_removesAllActions() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).addAction(action1)
- .addAction(action2)
- .clearActions()
- .addAction(action3)
- .build()
+ val safetySourceIssue =
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .addAction(action1)
+ .addAction(action2)
+ .clearActions()
+ .addAction(action3)
+ .build()
assertThat(safetySourceIssue.actions).containsExactly(action3)
}
@Test
fun getOnDismissPendingIntent_withDefaultBuilder_returnsNull() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).addAction(action1)
- .build()
+ val safetySourceIssue =
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .addAction(action1)
+ .build()
assertThat(safetySourceIssue.onDismissPendingIntent).isNull()
}
@Test
fun getOnDismissPendingIntent_whenSetExplicitly_returnsOnDismissPendingIntent() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).addAction(action1)
- .setOnDismissPendingIntent(pendingIntent1)
- .build()
+ val safetySourceIssue =
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .addAction(action1)
+ .setOnDismissPendingIntent(pendingIntentService)
+ .build()
- assertThat(safetySourceIssue.onDismissPendingIntent).isEqualTo(pendingIntent1)
+ assertThat(safetySourceIssue.onDismissPendingIntent).isEqualTo(pendingIntentService)
}
@Test
fun getIssueTypeId_returnsIssueTypeId() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).addAction(action1)
- .build()
+ val safetySourceIssue =
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .addAction(action1)
+ .build()
assertThat(safetySourceIssue.issueTypeId).isEqualTo("issue_type_id")
}
@Test
- fun build_withNoActions_throwsIllegalArgumentException() {
- val safetySourceIssueBuilder = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- )
+ fun build_withNullId_throwsNullPointerException() {
+ assertFailsWith(NullPointerException::class) {
+ SafetySourceIssue.Builder(
+ Generic.asNull(),
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ }
+ }
+
+ @Test
+ fun build_withNullTitle_throwsNullPointerException() {
+ assertFailsWith(NullPointerException::class) {
+ SafetySourceIssue.Builder(
+ "Issue id",
+ Generic.asNull(),
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ }
+ }
+
+ @Test
+ fun build_withNullSummary_throwsNullPointerException() {
+ assertFailsWith(NullPointerException::class) {
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ Generic.asNull(),
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ }
+ }
+ @Test
+ fun build_withInvalidSeverityLevel_throwsIllegalArgumentException() {
+ val exception = assertFailsWith(IllegalArgumentException::class) {
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_UNSPECIFIED,
+ "issue_type_id"
+ )
+ }
+ assertThat(exception).hasMessageThat().isEqualTo("Unexpected Level for issue: 100")
+ }
+
+ @Test
+ fun build_withNullIssueTypeId_throwsNullPointerException() {
+ assertFailsWith(NullPointerException::class) {
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ Generic.asNull()
+ )
+ }
+ }
+
+ @Test
+ fun build_withInvalidIssueCategory_throwsIllegalArgumentException() {
+ val builder =
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ val exception = assertFailsWith(IllegalArgumentException::class) {
+ builder.setIssueCategory(-1)
+ }
+ assertThat(exception).hasMessageThat().isEqualTo("Unexpected IssueCategory: -1")
+ }
+
+ @Test
+ fun build_withInvalidOnDismissPendingIntent_throwsIllegalArgumentException() {
+ val builder =
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
val exception = assertFailsWith(IllegalArgumentException::class) {
- safetySourceIssueBuilder.build()
+ builder.setOnDismissPendingIntent(
+ PendingIntent.getActivity(
+ context,
+ 0 /* requestCode= */,
+ Intent("PendingIntent activity"),
+ FLAG_IMMUTABLE
+ )
+ )
}
+ assertThat(exception).hasMessageThat()
+ .isEqualTo("Safety source issue on dismiss pending intent must not start an activity")
+ }
+
+ @Test
+ fun build_withNoActions_throwsIllegalArgumentException() {
+ val safetySourceIssueBuilder =
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+
+ val exception =
+ assertFailsWith(IllegalArgumentException::class) { safetySourceIssueBuilder.build() }
assertThat(exception)
.hasMessageThat()
.isEqualTo("Safety source issue must contain at least 1 action")
@@ -440,19 +533,20 @@ class SafetySourceIssueTest {
@Test
fun build_withMoreThanTwoActions_throwsIllegalArgumentException() {
- val safetySourceIssueBuilder = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).addAction(action1)
- .addAction(action2)
- .addAction(action1)
+ val safetySourceIssueBuilder =
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .addAction(action1)
+ .addAction(action2)
+ .addAction(action1)
- val exception = assertFailsWith(IllegalArgumentException::class) {
- safetySourceIssueBuilder.build()
- }
+ val exception =
+ assertFailsWith(IllegalArgumentException::class) { safetySourceIssueBuilder.build() }
assertThat(exception)
.hasMessageThat()
.isEqualTo("Safety source issue must not contain more than 2 actions")
@@ -460,331 +554,219 @@ class SafetySourceIssueTest {
@Test
fun describeContents_returns0() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).setSubtitle("Issue subtitle")
- .setIssueCategory(ISSUE_CATEGORY_ACCOUNT)
- .addAction(action1)
- .addAction(action2)
- .setOnDismissPendingIntent(pendingIntent1)
- .build()
+ val safetySourceIssue =
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .setSubtitle("Issue subtitle")
+ .setIssueCategory(ISSUE_CATEGORY_ACCOUNT)
+ .addAction(action1)
+ .addAction(action2)
+ .setOnDismissPendingIntent(pendingIntentService)
+ .build()
assertThat(safetySourceIssue.describeContents()).isEqualTo(0)
}
@Test
- fun createFromParcel_withWriteToParcel_returnsOriginalSafetySourceIssue() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).setSubtitle("Issue subtitle")
- .setIssueCategory(ISSUE_CATEGORY_ACCOUNT)
- .addAction(action1)
- .addAction(action2)
- .setOnDismissPendingIntent(pendingIntent1)
- .build()
-
- val parcel: Parcel = Parcel.obtain()
- safetySourceIssue.writeToParcel(parcel, 0 /* flags */)
- parcel.setDataPosition(0)
- val safetySourceIssueFromParcel: SafetySourceIssue =
- SafetySourceIssue.CREATOR.createFromParcel(parcel)
- parcel.recycle()
-
- assertThat(safetySourceIssueFromParcel).isEqualTo(safetySourceIssue)
- }
-
- // TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
- @Test
- fun hashCode_equals_toString_withEqualByReferenceSafetySourceIssues_areEqual() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).setSubtitle("Issue subtitle")
- .setIssueCategory(ISSUE_CATEGORY_ACCOUNT)
- .addAction(action1)
- .addAction(action2)
- .setOnDismissPendingIntent(pendingIntent1)
- .build()
- val otherSafetySourceIssue = safetySourceIssue
-
- assertThat(safetySourceIssue.hashCode()).isEqualTo(otherSafetySourceIssue.hashCode())
- assertThat(safetySourceIssue).isEqualTo(otherSafetySourceIssue)
- assertThat(safetySourceIssue.toString()).isEqualTo(otherSafetySourceIssue.toString())
- }
-
- @Test
- fun hashCode_equals_toString_withAllFieldsEqual_areEqual() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).setSubtitle("Issue subtitle")
- .setIssueCategory(ISSUE_CATEGORY_ACCOUNT)
- .addAction(
- Action.Builder("action_id", "Action label 1", pendingIntent1)
- .setWillResolve(false)
+ fun parcelRoundTrip_recreatesEqual() {
+ val safetySourceIssue =
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .setSubtitle("Issue subtitle")
+ .setIssueCategory(ISSUE_CATEGORY_ACCOUNT)
+ .addAction(action1)
+ .addAction(action2)
+ .setOnDismissPendingIntent(pendingIntentService)
+ .build()
+
+ assertThat(safetySourceIssue).recreatesEqual(SafetySourceIssue.CREATOR)
+ }
+
+ @Test
+ fun equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
+ EqualsHashCodeToStringTester()
+ .addEqualityGroup(
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .setSubtitle("Issue subtitle")
+ .setIssueCategory(ISSUE_CATEGORY_ACCOUNT)
+ .addAction(action1)
+ .addAction(action2)
+ .setOnDismissPendingIntent(pendingIntentService)
+ .build(),
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .setSubtitle("Issue subtitle")
+ .setIssueCategory(ISSUE_CATEGORY_ACCOUNT)
+ .addAction(action1)
+ .addAction(action2)
+ .setOnDismissPendingIntent(pendingIntentService)
.build()
)
- .setOnDismissPendingIntent(pendingIntent1)
- .build()
- val otherSafetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).setSubtitle("Issue subtitle")
- .setIssueCategory(ISSUE_CATEGORY_ACCOUNT)
- .addAction(
- Action.Builder("action_id", "Action label 1", pendingIntent1)
- .setWillResolve(false)
+ .addEqualityGroup(
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .addAction(action1)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySourceIssue.Builder(
+ "Other issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .addAction(action1)
.build()
)
- .setOnDismissPendingIntent(pendingIntent1)
- .build()
-
- assertThat(safetySourceIssue.hashCode()).isEqualTo(otherSafetySourceIssue.hashCode())
- assertThat(safetySourceIssue).isEqualTo(otherSafetySourceIssue)
- assertThat(safetySourceIssue.toString()).isEqualTo(otherSafetySourceIssue.toString())
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentIds_areNotEqual() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).addAction(action1)
- .build()
- val otherSafetySourceIssue = SafetySourceIssue.Builder(
- "Other issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).addAction(action1)
- .build()
-
- assertThat(safetySourceIssue.hashCode()).isNotEqualTo(otherSafetySourceIssue.hashCode())
- assertThat(safetySourceIssue).isNotEqualTo(otherSafetySourceIssue)
- assertThat(safetySourceIssue.toString()).isNotEqualTo(otherSafetySourceIssue.toString())
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentTitles_areNotEqual() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).addAction(action1)
- .build()
- val otherSafetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Other issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).addAction(action1)
- .build()
-
- assertThat(safetySourceIssue.hashCode()).isNotEqualTo(otherSafetySourceIssue.hashCode())
- assertThat(safetySourceIssue).isNotEqualTo(otherSafetySourceIssue)
- assertThat(safetySourceIssue.toString()).isNotEqualTo(otherSafetySourceIssue.toString())
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentSubtitles_areNotEqual() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).setSubtitle("Issue subtitle")
- .addAction(action1)
- .build()
- val otherSafetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).setSubtitle("Other issue subtitle")
- .addAction(action1)
- .build()
-
- assertThat(safetySourceIssue.hashCode()).isNotEqualTo(otherSafetySourceIssue.hashCode())
- assertThat(safetySourceIssue).isNotEqualTo(otherSafetySourceIssue)
- assertThat(safetySourceIssue.toString()).isNotEqualTo(otherSafetySourceIssue.toString())
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentSummaries_areNotEqual() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).addAction(action1)
- .build()
- val otherSafetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Other issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).addAction(action1)
- .build()
-
- assertThat(safetySourceIssue.hashCode()).isNotEqualTo(otherSafetySourceIssue.hashCode())
- assertThat(safetySourceIssue).isNotEqualTo(otherSafetySourceIssue)
- assertThat(safetySourceIssue.toString()).isNotEqualTo(otherSafetySourceIssue.toString())
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentSeverityLevels_areNotEqual() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).addAction(action1)
- .build()
- val otherSafetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_CRITICAL_WARNING,
- "issue_type_id"
- )
- .addAction(action1)
- .build()
-
- assertThat(safetySourceIssue.hashCode()).isNotEqualTo(otherSafetySourceIssue.hashCode())
- assertThat(safetySourceIssue).isNotEqualTo(otherSafetySourceIssue)
- assertThat(safetySourceIssue.toString()).isNotEqualTo(otherSafetySourceIssue.toString())
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentIssueCategories_areNotEqual() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- )
- .addAction(action1)
- .setIssueCategory(ISSUE_CATEGORY_DEVICE)
- .build()
- val otherSafetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- )
- .addAction(action1)
- .setIssueCategory(ISSUE_CATEGORY_GENERAL)
- .build()
-
- assertThat(safetySourceIssue.hashCode()).isNotEqualTo(otherSafetySourceIssue.hashCode())
- assertThat(safetySourceIssue).isNotEqualTo(otherSafetySourceIssue)
- assertThat(safetySourceIssue.toString()).isNotEqualTo(otherSafetySourceIssue.toString())
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentActions_areNotEqual() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).addAction(action1)
- .addAction(action2)
- .build()
- val otherSafetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).addAction(action2)
- .addAction(action1)
- .build()
-
- assertThat(safetySourceIssue.hashCode()).isNotEqualTo(otherSafetySourceIssue.hashCode())
- assertThat(safetySourceIssue).isNotEqualTo(otherSafetySourceIssue)
- assertThat(safetySourceIssue.toString()).isNotEqualTo(otherSafetySourceIssue.toString())
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentOnDismissPendingIntents_areNotEqual() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).addAction(action1)
- .setOnDismissPendingIntent(pendingIntent1)
- .build()
- val otherSafetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).addAction(action1)
- .setOnDismissPendingIntent(pendingIntent2)
- .build()
-
- assertThat(safetySourceIssue.hashCode()).isNotEqualTo(otherSafetySourceIssue.hashCode())
- assertThat(safetySourceIssue).isNotEqualTo(otherSafetySourceIssue)
- assertThat(safetySourceIssue.toString()).isNotEqualTo(otherSafetySourceIssue.toString())
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentIssueTypeIds_areNotEqual() {
- val safetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "issue_type_id"
- ).addAction(action1)
- .build()
- val otherSafetySourceIssue = SafetySourceIssue.Builder(
- "Issue id",
- "Issue title",
- "Issue summary",
- SEVERITY_LEVEL_INFORMATION,
- "other_issue_type_id"
- ).addAction(action1)
- .build()
-
- assertThat(safetySourceIssue.hashCode()).isNotEqualTo(otherSafetySourceIssue.hashCode())
- assertThat(safetySourceIssue).isNotEqualTo(otherSafetySourceIssue)
- assertThat(safetySourceIssue.toString()).isNotEqualTo(otherSafetySourceIssue.toString())
- }
-} \ No newline at end of file
+ .addEqualityGroup(
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Other issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .addAction(action1)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Other issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .addAction(action1)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_CRITICAL_WARNING,
+ "issue_type_id"
+ )
+ .addAction(action1)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "other_issue_type_id"
+ )
+ .addAction(action1)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .addAction(action2)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .setSubtitle("Other issue subtitle")
+ .setIssueCategory(ISSUE_CATEGORY_ACCOUNT)
+ .addAction(action1)
+ .addAction(action2)
+ .setOnDismissPendingIntent(pendingIntentService)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .setSubtitle("Other issue subtitle")
+ .setIssueCategory(ISSUE_CATEGORY_DEVICE)
+ .addAction(action1)
+ .addAction(action2)
+ .setOnDismissPendingIntent(pendingIntentService)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .setSubtitle("Other issue subtitle")
+ .setIssueCategory(ISSUE_CATEGORY_DEVICE)
+ .addAction(action2)
+ .addAction(action1)
+ .setOnDismissPendingIntent(pendingIntentService)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySourceIssue.Builder(
+ "Issue id",
+ "Issue title",
+ "Issue summary",
+ SEVERITY_LEVEL_INFORMATION,
+ "issue_type_id"
+ )
+ .setSubtitle("Other issue subtitle")
+ .setIssueCategory(ISSUE_CATEGORY_DEVICE)
+ .addAction(action2)
+ .addAction(action1)
+ .setOnDismissPendingIntent(
+ PendingIntent.getService(
+ context,
+ 0,
+ Intent("Other PendingIntent service"),
+ FLAG_IMMUTABLE
+ )
+ )
+ .build()
+ )
+ .test()
+ }
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceStatusTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceStatusTest.kt
index b44f6c5d3..3625b9ebc 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceStatusTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceStatusTest.kt
@@ -21,17 +21,21 @@ import android.app.PendingIntent.FLAG_IMMUTABLE
import android.content.Context
import android.content.Intent
import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
+import android.safetycenter.SafetySourceData.SEVERITY_LEVEL_CRITICAL_WARNING
+import android.safetycenter.SafetySourceData.SEVERITY_LEVEL_INFORMATION
+import android.safetycenter.SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED
import android.safetycenter.SafetySourceStatus
import android.safetycenter.SafetySourceStatus.IconAction
import android.safetycenter.SafetySourceStatus.IconAction.ICON_TYPE_GEAR
import android.safetycenter.SafetySourceStatus.IconAction.ICON_TYPE_INFO
-import android.safetycenter.SafetySourceStatus.STATUS_LEVEL_CRITICAL_WARNING
-import android.safetycenter.SafetySourceStatus.STATUS_LEVEL_OK
+import android.safetycenter.cts.testing.EqualsHashCodeToStringTester
+import android.safetycenter.cts.testing.Generic
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.ext.truth.os.ParcelableSubject.assertThat
import androidx.test.filters.SdkSuppress
import com.google.common.truth.Truth.assertThat
+import kotlin.test.assertFailsWith
import org.junit.Test
import org.junit.runner.RunWith
@@ -41,15 +45,11 @@ import org.junit.runner.RunWith
class SafetySourceStatusTest {
private val context: Context = getApplicationContext()
- private val pendingIntent1: PendingIntent = PendingIntent.getActivity(
- context,
- 0 /* requestCode= */, Intent("PendingIntent 1"), FLAG_IMMUTABLE
- )
+ private val pendingIntent1: PendingIntent =
+ PendingIntent.getActivity(context, 0, Intent("PendingIntent 1"), FLAG_IMMUTABLE)
private val iconAction1 = IconAction(ICON_TYPE_INFO, pendingIntent1)
- private val pendingIntent2: PendingIntent = PendingIntent.getActivity(
- context,
- 0 /* requestCode= */, Intent("PendingIntent 2"), FLAG_IMMUTABLE
- )
+ private val pendingIntent2: PendingIntent =
+ PendingIntent.getActivity(context, 0, Intent("PendingIntent 2"), FLAG_IMMUTABLE)
private val iconAction2 = IconAction(ICON_TYPE_GEAR, pendingIntent2)
@Test
@@ -67,392 +67,311 @@ class SafetySourceStatusTest {
}
@Test
- fun iconAction_describeContents_returns0() {
- val iconAction = IconAction(ICON_TYPE_GEAR, pendingIntent1)
-
- assertThat(iconAction.describeContents()).isEqualTo(0)
+ fun iconAction_build_withInvalidIconType_throwsIllegalArgumentException() {
+ val exception = assertFailsWith(IllegalArgumentException::class) {
+ IconAction(-1, pendingIntent1)
+ }
+ assertThat(exception).hasMessageThat().isEqualTo("Unexpected IconType: -1")
}
@Test
- fun iconAction_createFromParcel_withWriteToParcel_returnsOriginalAction() {
- val iconAction = IconAction(ICON_TYPE_GEAR, pendingIntent1)
-
- val parcel: Parcel = Parcel.obtain()
- iconAction.writeToParcel(parcel, 0 /* flags */)
- parcel.setDataPosition(0)
- val iconActionFromParcel: IconAction = IconAction.CREATOR.createFromParcel(parcel)
- parcel.recycle()
-
- assertThat(iconActionFromParcel).isEqualTo(iconAction)
+ fun iconAction_build_withNullPendingIntent_throwsNullPointerException() {
+ assertFailsWith(NullPointerException::class) {
+ IconAction(ICON_TYPE_INFO, Generic.asNull())
+ }
}
- // TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
@Test
- fun iconAction_hashCode_equals_toString_withEqualByReferenceIconActions_areEqual() {
- val iconAction = IconAction(ICON_TYPE_GEAR, pendingIntent1)
- val otherIconAction = iconAction
-
- assertThat(iconAction.hashCode()).isEqualTo(otherIconAction.hashCode())
- assertThat(iconAction).isEqualTo(otherIconAction)
- assertThat(iconAction.toString()).isEqualTo(otherIconAction.toString())
- }
-
- @Test
- fun iconAction_hashCode_equals_toString_withAllFieldsEqual_areEqual() {
+ fun iconAction_describeContents_returns0() {
val iconAction = IconAction(ICON_TYPE_GEAR, pendingIntent1)
- val otherIconAction = IconAction(ICON_TYPE_GEAR, pendingIntent1)
- assertThat(iconAction.hashCode()).isEqualTo(otherIconAction.hashCode())
- assertThat(iconAction).isEqualTo(otherIconAction)
- assertThat(iconAction.toString()).isEqualTo(otherIconAction.toString())
+ assertThat(iconAction.describeContents()).isEqualTo(0)
}
@Test
- fun iconAction_hashCode_equals_toString_withDifferentIconTypes_areNotEqual() {
+ fun iconAction_parcelRoundTrip_recreatesEqual() {
val iconAction = IconAction(ICON_TYPE_GEAR, pendingIntent1)
- val otherIconAction = IconAction(ICON_TYPE_INFO, pendingIntent1)
- assertThat(iconAction.hashCode()).isNotEqualTo(otherIconAction.hashCode())
- assertThat(iconAction).isNotEqualTo(otherIconAction)
- assertThat(iconAction.toString()).isNotEqualTo(otherIconAction.toString())
+ assertThat(iconAction).recreatesEqual(IconAction.CREATOR)
}
@Test
- fun iconAction_hashCode_equals_toString_withDifferentPendingIntents_areNotEqual() {
- val iconAction = IconAction(ICON_TYPE_GEAR, pendingIntent1)
- val otherIconAction = IconAction(ICON_TYPE_GEAR, pendingIntent2)
-
- assertThat(iconAction.hashCode()).isNotEqualTo(otherIconAction.hashCode())
- assertThat(iconAction).isNotEqualTo(otherIconAction)
- assertThat(iconAction.toString()).isNotEqualTo(otherIconAction.toString())
+ fun iconAction_equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
+ EqualsHashCodeToStringTester()
+ .addEqualityGroup(
+ IconAction(ICON_TYPE_GEAR, pendingIntent1),
+ IconAction(ICON_TYPE_GEAR, pendingIntent1)
+ )
+ .addEqualityGroup(IconAction(ICON_TYPE_INFO, pendingIntent1))
+ .addEqualityGroup(IconAction(ICON_TYPE_GEAR, pendingIntent2))
+ .test()
}
@Test
fun getTitle_returnsTitle() {
- val safetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Status summary",
- STATUS_LEVEL_OK,
- pendingIntent1
- )
- .build()
+ val safetySourceStatus =
+ SafetySourceStatus.Builder("Status title", "Status summary", SEVERITY_LEVEL_INFORMATION)
+ .build()
assertThat(safetySourceStatus.title).isEqualTo("Status title")
}
@Test
fun getSummary_returnsSummary() {
- val safetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Status summary",
- STATUS_LEVEL_OK,
- pendingIntent1
- )
- .build()
+ val safetySourceStatus =
+ SafetySourceStatus.Builder("Status title", "Status summary", SEVERITY_LEVEL_INFORMATION)
+ .build()
assertThat(safetySourceStatus.summary).isEqualTo("Status summary")
}
@Test
- fun getStatusLevel_returnsStatusLevel() {
- val safetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Status summary",
- STATUS_LEVEL_OK,
- pendingIntent1
- )
- .build()
+ fun getSeverityLevel_returnsSeverityLevel() {
+ val safetySourceStatus =
+ SafetySourceStatus.Builder("Status title", "Status summary", SEVERITY_LEVEL_INFORMATION)
+ .build()
- assertThat(safetySourceStatus.statusLevel).isEqualTo(STATUS_LEVEL_OK)
+ assertThat(safetySourceStatus.severityLevel).isEqualTo(SEVERITY_LEVEL_INFORMATION)
}
@Test
- fun getPendingIntent_returnsPendingIntent() {
- val safetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Status summary",
- STATUS_LEVEL_OK,
- pendingIntent1
- )
- .build()
+ fun getPendingIntent_withDefaultBuilder_returnsNull() {
+ val safetySourceStatus =
+ SafetySourceStatus.Builder("Status title", "Status summary", SEVERITY_LEVEL_INFORMATION)
+ .build()
+
+ assertThat(safetySourceStatus.pendingIntent).isNull()
+ }
+
+ @Test
+ fun getPendingIntent_whenSetExplicitly_returnsPendingIntent() {
+ val safetySourceStatus =
+ SafetySourceStatus.Builder("Status title", "Status summary", SEVERITY_LEVEL_INFORMATION)
+ .setPendingIntent(pendingIntent1)
+ .build()
assertThat(safetySourceStatus.pendingIntent).isEqualTo(pendingIntent1)
}
@Test
fun getIconAction_withDefaultBuilder_returnsNull() {
- val safetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Status summary",
- STATUS_LEVEL_OK,
- pendingIntent1
- )
- .build()
+ val safetySourceStatus =
+ SafetySourceStatus.Builder("Status title", "Status summary", SEVERITY_LEVEL_INFORMATION)
+ .build()
assertThat(safetySourceStatus.iconAction).isNull()
}
@Test
fun getIconAction_whenSetExplicitly_returnsIconAction() {
- val safetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Status summary",
- STATUS_LEVEL_OK,
- pendingIntent1
- )
- .setIconAction(iconAction1)
- .build()
+ val safetySourceStatus =
+ SafetySourceStatus.Builder("Status title", "Status summary", SEVERITY_LEVEL_INFORMATION)
+ .setIconAction(iconAction1)
+ .build()
assertThat(safetySourceStatus.iconAction).isEqualTo(iconAction1)
}
@Test
fun isEnabled_withDefaultBuilder_returnsTrue() {
- val safetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Status summary",
- STATUS_LEVEL_OK,
- pendingIntent1
- )
- .build()
+ val safetySourceStatus =
+ SafetySourceStatus.Builder("Status title", "Status summary", SEVERITY_LEVEL_UNSPECIFIED)
+ .build()
assertThat(safetySourceStatus.isEnabled).isTrue()
}
@Test
fun isEnabled_whenSetExplicitly_returnsEnabled() {
- val safetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Status summary",
- STATUS_LEVEL_OK,
- pendingIntent1
- )
- .setEnabled(false)
- .build()
+ val safetySourceStatus =
+ SafetySourceStatus.Builder("Status title", "Status summary", SEVERITY_LEVEL_UNSPECIFIED)
+ .setEnabled(false)
+ .build()
assertThat(safetySourceStatus.isEnabled).isFalse()
}
@Test
- fun describeContents_returns0() {
- val safetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Status summary",
- STATUS_LEVEL_OK,
- pendingIntent1
- )
- .setIconAction(iconAction1)
- .build()
-
- assertThat(safetySourceStatus.describeContents()).isEqualTo(0)
+ fun build_withNullTitle_throwsNullPointerException() {
+ assertFailsWith(NullPointerException::class) {
+ SafetySourceStatus.Builder(
+ Generic.asNull(),
+ "Status summary",
+ SEVERITY_LEVEL_INFORMATION
+ )
+ }
}
@Test
- fun createFromParcel_withWriteToParcel_returnsOriginalSafetySourceStatus() {
- val safetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Status summary",
- STATUS_LEVEL_OK,
- pendingIntent1
- )
- .setIconAction(iconAction1)
- .setEnabled(true)
- .build()
-
- val parcel: Parcel = Parcel.obtain()
- safetySourceStatus.writeToParcel(parcel, 0 /* flags */)
- parcel.setDataPosition(0)
- val safetySourceStatusFromParcel: SafetySourceStatus =
- SafetySourceStatus.CREATOR.createFromParcel(parcel)
- parcel.recycle()
-
- assertThat(safetySourceStatusFromParcel).isEqualTo(safetySourceStatus)
+ fun build_withNullSummary_throwsNullPointerException() {
+ assertFailsWith(NullPointerException::class) {
+ SafetySourceStatus.Builder(
+ "Status title",
+ Generic.asNull(),
+ SEVERITY_LEVEL_INFORMATION
+ )
+ }
}
- // TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
@Test
- fun hashCode_equals_toString_withEqualByReferenceSafetySourceStatuses_areEqual() {
- val safetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Status summary",
- STATUS_LEVEL_OK,
- pendingIntent1
- )
- .setIconAction(iconAction1)
- .setEnabled(true)
- .build()
- val otherSafetySourceStatus = safetySourceStatus
-
- assertThat(safetySourceStatus.hashCode()).isEqualTo(otherSafetySourceStatus.hashCode())
- assertThat(safetySourceStatus).isEqualTo(otherSafetySourceStatus)
- assertThat(safetySourceStatus.toString()).isEqualTo(otherSafetySourceStatus.toString())
+ fun build_withInvalidSeverityLevel_throwsIllegalArgumentException() {
+ val exception = assertFailsWith(IllegalArgumentException::class) {
+ SafetySourceStatus.Builder(
+ "Status title",
+ "Status summary",
+ -1
+ )
+ }
+ assertThat(exception).hasMessageThat().isEqualTo("Unexpected Level for source: -1")
}
@Test
- fun hashCode_equals_toString_withAllFieldsEqual_areEqual() {
- val safetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Status summary",
- STATUS_LEVEL_OK,
- pendingIntent1
- )
- .setIconAction(iconAction1)
- .setEnabled(true)
- .build()
- val otherSafetySourceStatus = SafetySourceStatus.Builder(
+ fun build_withInvalidPendingIntent_throwsIllegalArgumentException() {
+ val builder = SafetySourceStatus.Builder(
"Status title",
"Status summary",
- STATUS_LEVEL_OK,
- pendingIntent1
+ SEVERITY_LEVEL_INFORMATION
)
- .setIconAction(iconAction1)
- .setEnabled(true)
- .build()
-
- assertThat(safetySourceStatus.hashCode()).isEqualTo(otherSafetySourceStatus.hashCode())
- assertThat(safetySourceStatus).isEqualTo(otherSafetySourceStatus)
- assertThat(safetySourceStatus.toString()).isEqualTo(otherSafetySourceStatus.toString())
+ val exception = assertFailsWith(IllegalArgumentException::class) {
+ builder.setPendingIntent(
+ PendingIntent.getService(
+ context,
+ 0 /* requestCode= */,
+ Intent("PendingIntent service"),
+ FLAG_IMMUTABLE
+ )
+ )
+ }
+ assertThat(exception).hasMessageThat()
+ .isEqualTo("Safety source status pending intent must start an activity")
}
@Test
- fun hashCode_equals_toString_withDifferentTitles_areNotEqual() {
- val safetySourceStatus = SafetySourceStatus.Builder(
+ fun build_withInvalidEnabledState_throwsIllegalArgumentException() {
+ val builder = SafetySourceStatus.Builder(
"Status title",
"Status summary",
- STATUS_LEVEL_OK,
- pendingIntent1
+ SEVERITY_LEVEL_INFORMATION
)
- .build()
- val otherSafetySourceStatus = SafetySourceStatus.Builder(
- "Other status title",
- "Status summary",
- STATUS_LEVEL_OK,
- pendingIntent1
- )
- .build()
-
- assertThat(safetySourceStatus.hashCode()).isNotEqualTo(otherSafetySourceStatus.hashCode())
- assertThat(safetySourceStatus).isNotEqualTo(otherSafetySourceStatus)
- assertThat(safetySourceStatus.toString()).isNotEqualTo(otherSafetySourceStatus.toString())
+ val exception = assertFailsWith(IllegalArgumentException::class) {
+ builder.setEnabled(false)
+ }
+ assertThat(exception).hasMessageThat()
+ .isEqualTo(
+ "Safety source status must have a severity level of SEVERITY_LEVEL_UNSPECIFIED" +
+ " when disabled"
+ )
}
@Test
- fun hashCode_equals_toString_withDifferentSummaries_areNotEqual() {
- val safetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Status summary",
- STATUS_LEVEL_OK,
- pendingIntent1
- )
- .build()
- val otherSafetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Other status summary",
- STATUS_LEVEL_OK,
- pendingIntent1
- )
- .build()
+ fun describeContents_returns0() {
+ val safetySourceStatus =
+ SafetySourceStatus.Builder("Status title", "Status summary", SEVERITY_LEVEL_INFORMATION)
+ .setPendingIntent(pendingIntent1)
+ .setIconAction(iconAction1)
+ .build()
- assertThat(safetySourceStatus.hashCode()).isNotEqualTo(otherSafetySourceStatus.hashCode())
- assertThat(safetySourceStatus).isNotEqualTo(otherSafetySourceStatus)
- assertThat(safetySourceStatus.toString()).isNotEqualTo(otherSafetySourceStatus.toString())
+ assertThat(safetySourceStatus.describeContents()).isEqualTo(0)
}
@Test
- fun hashCode_equals_toString_withDifferentStatusLevels_areNotEqual() {
- val safetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Status summary",
- STATUS_LEVEL_OK,
- pendingIntent1
- )
- .build()
- val otherSafetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Status summary",
- STATUS_LEVEL_CRITICAL_WARNING,
- pendingIntent1
- )
- .build()
-
- assertThat(safetySourceStatus.hashCode()).isNotEqualTo(otherSafetySourceStatus.hashCode())
- assertThat(safetySourceStatus).isNotEqualTo(otherSafetySourceStatus)
- assertThat(safetySourceStatus.toString()).isNotEqualTo(otherSafetySourceStatus.toString())
+ fun parcelRoundTrip_recreatesEqual() {
+ val safetySourceStatus =
+ SafetySourceStatus.Builder("Status title", "Status summary", SEVERITY_LEVEL_INFORMATION)
+ .setPendingIntent(pendingIntent1)
+ .setIconAction(iconAction1)
+ .setEnabled(true)
+ .build()
+ val safetySourceStatusWithMinimalFields =
+ SafetySourceStatus.Builder("Status title", "Status summary", SEVERITY_LEVEL_INFORMATION)
+ .build()
+
+ assertThat(safetySourceStatus).recreatesEqual(SafetySourceStatus.CREATOR)
+ assertThat(safetySourceStatusWithMinimalFields).recreatesEqual(SafetySourceStatus.CREATOR)
}
@Test
- fun hashCode_equals_toString_withDifferentPendingIntents_areNotEqual() {
- val safetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Status summary",
- STATUS_LEVEL_OK,
- PendingIntent.getActivity(
- context, 0 /* requestCode= */,
- Intent("Status PendingIntent"), FLAG_IMMUTABLE
+ fun equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
+ EqualsHashCodeToStringTester()
+ .addEqualityGroup(
+ SafetySourceStatus.Builder(
+ "Status title",
+ "Status summary",
+ SEVERITY_LEVEL_INFORMATION
+ )
+ .setPendingIntent(pendingIntent1)
+ .setIconAction(iconAction1)
+ .setEnabled(true)
+ .build(),
+ SafetySourceStatus.Builder(
+ "Status title",
+ "Status summary",
+ SEVERITY_LEVEL_INFORMATION
+ )
+ .setPendingIntent(pendingIntent1)
+ .setIconAction(iconAction1)
+ .setEnabled(true)
+ .build()
)
- )
- .build()
- val otherSafetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Status summary",
- STATUS_LEVEL_CRITICAL_WARNING,
- PendingIntent.getActivity(
- context, 0 /* requestCode= */,
- Intent("Other status PendingIntent"), FLAG_IMMUTABLE
+ .addEqualityGroup(
+ SafetySourceStatus.Builder(
+ "Status title",
+ "Status summary",
+ SEVERITY_LEVEL_INFORMATION
+ )
+ .build()
)
- )
- .build()
-
- assertThat(safetySourceStatus.hashCode()).isNotEqualTo(otherSafetySourceStatus.hashCode())
- assertThat(safetySourceStatus).isNotEqualTo(otherSafetySourceStatus)
- assertThat(safetySourceStatus.toString()).isNotEqualTo(otherSafetySourceStatus.toString())
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentIconActions_areNotEqual() {
- val safetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Status summary",
- STATUS_LEVEL_CRITICAL_WARNING,
- pendingIntent1
- )
- .setIconAction(iconAction1)
- .build()
- val otherSafetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Status summary",
- STATUS_LEVEL_CRITICAL_WARNING,
- pendingIntent1
- )
- .setIconAction(iconAction2)
- .build()
-
- assertThat(safetySourceStatus.hashCode()).isNotEqualTo(otherSafetySourceStatus.hashCode())
- assertThat(safetySourceStatus).isNotEqualTo(otherSafetySourceStatus)
- assertThat(safetySourceStatus.toString()).isNotEqualTo(otherSafetySourceStatus.toString())
- }
-
- @Test
- fun hashCode_equals_toString_withDifferentEnabled_areNotEqual() {
- val safetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Status summary",
- STATUS_LEVEL_CRITICAL_WARNING,
- pendingIntent1
- )
- .setEnabled(true)
- .build()
- val otherSafetySourceStatus = SafetySourceStatus.Builder(
- "Status title",
- "Status summary",
- STATUS_LEVEL_CRITICAL_WARNING,
- pendingIntent1
- )
- .setEnabled(false)
- .build()
-
- assertThat(safetySourceStatus.hashCode()).isNotEqualTo(otherSafetySourceStatus.hashCode())
- assertThat(safetySourceStatus).isNotEqualTo(otherSafetySourceStatus)
- assertThat(safetySourceStatus.toString()).isNotEqualTo(otherSafetySourceStatus.toString())
+ .addEqualityGroup(
+ SafetySourceStatus.Builder(
+ "Other status title",
+ "Status summary",
+ SEVERITY_LEVEL_INFORMATION
+ )
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySourceStatus.Builder(
+ "Status title",
+ "Other status summary",
+ SEVERITY_LEVEL_INFORMATION
+ )
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySourceStatus.Builder(
+ "Status title",
+ "Status summary",
+ SEVERITY_LEVEL_CRITICAL_WARNING
+ )
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySourceStatus.Builder(
+ "Status title",
+ "Status summary",
+ SEVERITY_LEVEL_CRITICAL_WARNING
+ )
+ .setPendingIntent(pendingIntent2)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySourceStatus.Builder(
+ "Status title",
+ "Status summary",
+ SEVERITY_LEVEL_CRITICAL_WARNING
+ )
+ .setIconAction(iconAction2)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySourceStatus.Builder(
+ "Status title",
+ "Status summary",
+ SEVERITY_LEVEL_UNSPECIFIED
+ )
+ .setEnabled(false)
+ .build()
+ )
+ .test()
}
-} \ No newline at end of file
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/config/cts/ParseExceptionTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/config/ParseExceptionTest.kt
index 3a973e382..e805757a7 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/config/cts/ParseExceptionTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/config/ParseExceptionTest.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.safetycenter.config.cts
+package android.safetycenter.cts.config
import android.os.Build.VERSION_CODES.TIRAMISU
import android.safetycenter.config.ParseException
@@ -28,6 +28,7 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
class ParseExceptionTest {
+
@Test
fun propagatesMessage() {
val message = "error message"
@@ -48,4 +49,4 @@ class ParseExceptionTest {
assertThat(exception).hasMessageThat().isEqualTo(message)
assertThat(exception).hasCauseThat().isEqualTo(cause)
}
-} \ No newline at end of file
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/config/ParserConfigInvalidTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/config/ParserConfigInvalidTest.kt
new file mode 100644
index 000000000..ca3d1c7f2
--- /dev/null
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/config/ParserConfigInvalidTest.kt
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.safetycenter.cts.config
+
+import android.content.Context
+import android.os.Build.VERSION_CODES.TIRAMISU
+import android.safetycenter.config.ParseException
+import android.safetycenter.config.SafetyCenterConfig
+import android.safetycenter.cts.R
+import androidx.test.core.app.ApplicationProvider.getApplicationContext
+import androidx.test.filters.SdkSuppress
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.assertThrows
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
+class ParserConfigInvalidTest {
+ private val context: Context = getApplicationContext()
+
+ data class Params(
+ private val testName: String,
+ val configResourceId: Int,
+ val errorMessage: String,
+ val causeErrorMessage: String?
+ ) {
+ override fun toString() = testName
+ }
+
+ @Parameterized.Parameter
+ lateinit var params: Params
+
+ @Test
+ fun invalidConfig_throws() {
+ val parser = context.resources.getXml(params.configResourceId)
+
+ val thrown = assertThrows(ParseException::class.java) { SafetyCenterConfig.fromXml(parser) }
+
+ assertThat(thrown).hasMessageThat().isEqualTo(params.errorMessage)
+ if (params.causeErrorMessage != null) {
+ assertThat(thrown.cause).hasMessageThat().isEqualTo(params.causeErrorMessage)
+ }
+ }
+
+ companion object {
+ @JvmStatic
+ @Parameterized.Parameters(name = "{0}")
+ fun parameters() =
+ arrayOf(
+ Params(
+ "ConfigDynamicSafetySourceAllDisabledNoWork",
+ R.xml.config_dynamic_safety_source_all_disabled_no_work,
+ "Element dynamic-safety-source invalid",
+ "Required attribute titleForWork missing"
+ ),
+ Params(
+ "ConfigDynamicSafetySourceAllNoWork",
+ R.xml.config_dynamic_safety_source_all_no_work,
+ "Element dynamic-safety-source invalid",
+ "Required attribute titleForWork missing"
+ ),
+ Params(
+ "ConfigDynamicSafetySourceDisabledNoSummary",
+ R.xml.config_dynamic_safety_source_disabled_no_summary,
+ "Element dynamic-safety-source invalid",
+ "Required attribute summary missing"
+ ),
+ Params(
+ "ConfigDynamicSafetySourceDisabledNoTitle",
+ R.xml.config_dynamic_safety_source_disabled_no_title,
+ "Element dynamic-safety-source invalid",
+ "Required attribute title missing"
+ ),
+ Params(
+ "ConfigDynamicSafetySourceDuplicateKey",
+ R.xml.config_dynamic_safety_source_duplicate_key,
+ "Element safety-sources-config invalid",
+ "Duplicate id id among safety sources"
+ ),
+ Params(
+ "ConfigDynamicSafetySourceHiddenWithIntent",
+ R.xml.config_dynamic_safety_source_hidden_with_intent,
+ "Element dynamic-safety-source invalid",
+ "Prohibited attribute intentAction present"
+ ),
+ Params(
+ "ConfigDynamicSafetySourceHiddenWithSummary",
+ R.xml.config_dynamic_safety_source_hidden_with_summary,
+ "Element dynamic-safety-source invalid",
+ "Prohibited attribute summary present"
+ ),
+ Params(
+ "ConfigDynamicSafetySourceHiddenWithTitle",
+ R.xml.config_dynamic_safety_source_hidden_with_title,
+ "Element dynamic-safety-source invalid",
+ "Prohibited attribute title present"
+ ),
+ Params(
+ "ConfigDynamicSafetySourceInvalidDisplay",
+ R.xml.config_dynamic_safety_source_invalid_display,
+ "Attribute dynamic-safety-source.initialDisplayState invalid",
+ null
+ ),
+ Params(
+ "ConfigDynamicSafetySourceInvalidProfile",
+ R.xml.config_dynamic_safety_source_invalid_profile,
+ "Attribute dynamic-safety-source.profile invalid",
+ null
+ ),
+ Params(
+ "ConfigDynamicSafetySourceNoId",
+ R.xml.config_dynamic_safety_source_no_id,
+ "Element dynamic-safety-source invalid",
+ "Required attribute id missing"
+ ),
+ Params(
+ "ConfigDynamicSafetySourceNoIntent",
+ R.xml.config_dynamic_safety_source_no_intent,
+ "Element dynamic-safety-source invalid",
+ "Required attribute intentAction missing"
+ ),
+ Params(
+ "ConfigDynamicSafetySourceNoPackage",
+ R.xml.config_dynamic_safety_source_no_package,
+ "Element dynamic-safety-source invalid",
+ "Required attribute packageName missing"
+ ),
+ Params(
+ "ConfigDynamicSafetySourceNoProfile",
+ R.xml.config_dynamic_safety_source_no_profile,
+ "Element dynamic-safety-source invalid",
+ "Required attribute profile missing"
+ ),
+ Params(
+ "ConfigDynamicSafetySourceNoSummary",
+ R.xml.config_dynamic_safety_source_no_summary,
+ "Element dynamic-safety-source invalid",
+ "Required attribute summary missing"
+ ),
+ Params(
+ "ConfigDynamicSafetySourceNoTitle",
+ R.xml.config_dynamic_safety_source_no_title,
+ "Element dynamic-safety-source invalid",
+ "Required attribute title missing"
+ ),
+ Params(
+ "ConfigDynamicSafetySourcePrimaryHiddenWithWork",
+ R.xml.config_dynamic_safety_source_primary_hidden_with_work,
+ "Element dynamic-safety-source invalid",
+ "Prohibited attribute titleForWork present"
+ ),
+ Params(
+ "ConfigDynamicSafetySourcePrimaryWithWork",
+ R.xml.config_dynamic_safety_source_primary_with_work,
+ "Element dynamic-safety-source invalid",
+ "Prohibited attribute titleForWork present"
+ ),
+ Params(
+ "ConfigIssueOnlySafetySourceDuplicateKey",
+ R.xml.config_issue_only_safety_source_duplicate_key,
+ "Element safety-sources-config invalid",
+ "Duplicate id id among safety sources"
+ ),
+ Params(
+ "ConfigIssueOnlySafetySourceInvalidProfile",
+ R.xml.config_issue_only_safety_source_invalid_profile,
+ "Attribute issue-only-safety-source.profile invalid",
+ null
+ ),
+ Params(
+ "ConfigIssueOnlySafetySourceNoId",
+ R.xml.config_issue_only_safety_source_no_id,
+ "Element issue-only-safety-source invalid",
+ "Required attribute id missing"
+ ),
+ Params(
+ "ConfigIssueOnlySafetySourceNoPackage",
+ R.xml.config_issue_only_safety_source_no_package,
+ "Element issue-only-safety-source invalid",
+ "Required attribute packageName missing"
+ ),
+ Params(
+ "ConfigIssueOnlySafetySourceNoProfile",
+ R.xml.config_issue_only_safety_source_no_profile,
+ "Element issue-only-safety-source invalid",
+ "Required attribute profile missing"
+ ),
+ Params(
+ "ConfigIssueOnlySafetySourceWithDisplay",
+ R.xml.config_issue_only_safety_source_with_display,
+ "Element issue-only-safety-source invalid",
+ "Prohibited attribute initialDisplayState present"
+ ),
+ Params(
+ "ConfigIssueOnlySafetySourceWithIntent",
+ R.xml.config_issue_only_safety_source_with_intent,
+ "Element issue-only-safety-source invalid",
+ "Prohibited attribute intentAction present"
+ ),
+ Params(
+ "ConfigIssueOnlySafetySourceWithSearch",
+ R.xml.config_issue_only_safety_source_with_search,
+ "Element issue-only-safety-source invalid",
+ "Prohibited attribute searchTerms present"
+ ),
+ Params(
+ "ConfigIssueOnlySafetySourceWithSummary",
+ R.xml.config_issue_only_safety_source_with_summary,
+ "Element issue-only-safety-source invalid",
+ "Prohibited attribute summary present"
+ ),
+ Params(
+ "ConfigIssueOnlySafetySourceWithTitle",
+ R.xml.config_issue_only_safety_source_with_title,
+ "Element issue-only-safety-source invalid",
+ "Prohibited attribute title present"
+ ),
+ Params(
+ "ConfigIssueOnlySafetySourceWithWork",
+ R.xml.config_issue_only_safety_source_with_work,
+ "Element issue-only-safety-source invalid",
+ "Prohibited attribute titleForWork present"
+ ),
+ Params(
+ "ConfigMixedSafetySourceDuplicateKey",
+ R.xml.config_mixed_safety_source_duplicate_key,
+ "Element safety-sources-config invalid",
+ "Duplicate id id among safety sources"
+ ),
+ Params(
+ "ConfigReferenceInvalid",
+ R.xml.config_reference_invalid,
+ "Reference title in safety-sources-group.title missing or invalid",
+ null
+ ),
+ Params(
+ "ConfigSafetyCenterConfigMissing",
+ R.xml.config_safety_center_config_missing,
+ "Element safety-center-config missing",
+ null
+ ),
+ Params(
+ "ConfigSafetySourcesConfigEmpty",
+ R.xml.config_safety_sources_config_empty,
+ "Element safety-sources-config invalid",
+ "No safety sources groups present"
+ ),
+ Params(
+ "ConfigSafetySourcesConfigMissing",
+ R.xml.config_safety_sources_config_missing,
+ "Element safety-sources-config missing",
+ null
+ ),
+ Params(
+ "ConfigSafetySourcesGroupDuplicateId",
+ R.xml.config_safety_sources_group_duplicate_id,
+ "Element safety-sources-config invalid",
+ "Duplicate id id among safety sources groups"
+ ),
+ Params(
+ "ConfigSafetySourcesGroupEmpty",
+ R.xml.config_safety_sources_group_empty,
+ "Element safety-sources-group invalid",
+ "Safety sources group empty"
+ ),
+ Params(
+ "ConfigSafetySourcesGroupInvalidIcon",
+ R.xml.config_safety_sources_group_invalid_icon,
+ "Attribute safety-sources-group.statelessIconType invalid",
+ null
+ ),
+ Params(
+ "ConfigSafetySourcesGroupNoId",
+ R.xml.config_safety_sources_group_no_id,
+ "Element safety-sources-group invalid",
+ "Required attribute id missing"
+ ),
+ Params(
+ "ConfigSafetySourcesGroupNoTitle",
+ R.xml.config_safety_sources_group_no_title,
+ "Element safety-sources-group invalid",
+ "Required attribute title missing"
+ ),
+ Params(
+ "ConfigStaticSafetySourceDuplicateKey",
+ R.xml.config_static_safety_source_duplicate_key,
+ "Element safety-sources-config invalid",
+ "Duplicate id id among safety sources"
+ ),
+ Params(
+ "ConfigStaticSafetySourceInvalidProfile",
+ R.xml.config_static_safety_source_invalid_profile,
+ "Attribute static-safety-source.profile invalid",
+ null
+ ),
+ Params(
+ "ConfigStaticSafetySourceNoId",
+ R.xml.config_static_safety_source_no_id,
+ "Element static-safety-source invalid",
+ "Required attribute id missing"
+ ),
+ Params(
+ "ConfigStaticSafetySourceNoIntent",
+ R.xml.config_static_safety_source_no_intent,
+ "Element static-safety-source invalid",
+ "Required attribute intentAction missing"
+ ),
+ Params(
+ "ConfigStaticSafetySourceNoProfile",
+ R.xml.config_static_safety_source_no_profile,
+ "Element static-safety-source invalid",
+ "Required attribute profile missing"
+ ),
+ Params(
+ "ConfigStaticSafetySourceNoSummary",
+ R.xml.config_static_safety_source_no_summary,
+ "Element static-safety-source invalid",
+ "Required attribute summary missing"
+ ),
+ Params(
+ "ConfigStaticSafetySourceNoTitle",
+ R.xml.config_static_safety_source_no_title,
+ "Element static-safety-source invalid",
+ "Required attribute title missing"
+ ),
+ Params(
+ "ConfigStaticSafetySourceWithDisplay",
+ R.xml.config_static_safety_source_with_display,
+ "Element static-safety-source invalid",
+ "Prohibited attribute initialDisplayState present"
+ ),
+ Params(
+ "ConfigStaticSafetySourceWithLogging",
+ R.xml.config_static_safety_source_with_logging,
+ "Element static-safety-source invalid",
+ "Prohibited attribute loggingAllowed present"
+ ),
+ Params(
+ "ConfigStaticSafetySourceWithPackage",
+ R.xml.config_static_safety_source_with_package,
+ "Element static-safety-source invalid",
+ "Prohibited attribute packageName present"
+ ),
+ Params(
+ "ConfigStaticSafetySourceWithPrimaryAndWork",
+ R.xml.config_static_safety_source_with_primary_and_work,
+ "Element static-safety-source invalid",
+ "Prohibited attribute titleForWork present"
+ ),
+ Params(
+ "ConfigStaticSafetySourceWithRefresh",
+ R.xml.config_static_safety_source_with_refresh,
+ "Element static-safety-source invalid",
+ "Prohibited attribute refreshOnPageOpenAllowed present"
+ ),
+ Params(
+ "ConfigStaticSafetySourceWithSeverity",
+ R.xml.config_static_safety_source_with_severity,
+ "Element static-safety-source invalid",
+ "Prohibited attribute maxSeverityLevel present"
+ )
+ )
+ }
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/config/ParserConfigValidTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/config/ParserConfigValidTest.kt
new file mode 100644
index 000000000..675ecf95e
--- /dev/null
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/config/ParserConfigValidTest.kt
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.safetycenter.cts.config
+
+import android.content.Context
+import android.os.Build.VERSION_CODES.TIRAMISU
+import android.safetycenter.config.SafetyCenterConfig
+import android.safetycenter.config.SafetySource
+import android.safetycenter.config.SafetySourcesGroup
+import android.safetycenter.cts.R
+import androidx.test.core.app.ApplicationProvider.getApplicationContext
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
+class ParserConfigValidTest {
+ private val context: Context = getApplicationContext()
+
+ @Test
+ fun validConfig_matchesExpected() {
+ val parser = context.resources.getXml(R.xml.config_valid)
+
+ val actual = SafetyCenterConfig.fromXml(parser)
+
+ val expected =
+ SafetyCenterConfig.Builder()
+ .addSafetySourcesGroup(
+ SafetySourcesGroup.Builder()
+ .setId("dynamic")
+ .setTitleResId(R.string.reference)
+ .setSummaryResId(R.string.reference)
+ .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
+ .addSafetySource(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId("dynamic_barebone")
+ .setPackageName("package")
+ .setTitleResId(R.string.reference)
+ .setSummaryResId(R.string.reference)
+ .setIntentAction("intent")
+ .setProfile(SafetySource.PROFILE_PRIMARY)
+ .build()
+ )
+ .addSafetySource(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId("dynamic_all_optional")
+ .setPackageName("package")
+ .setTitleResId(R.string.reference)
+ .setTitleForWorkResId(R.string.reference)
+ .setSummaryResId(R.string.reference)
+ .setIntentAction("intent")
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
+ .setMaxSeverityLevel(300)
+ .setSearchTermsResId(R.string.reference)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
+ .build()
+ )
+ .addSafetySource(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId("dynamic_disabled")
+ .setPackageName("package")
+ .setTitleResId(R.string.reference)
+ .setSummaryResId(R.string.reference)
+ .setProfile(SafetySource.PROFILE_PRIMARY)
+ .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
+ .build()
+ )
+ .addSafetySource(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId("dynamic_hidden")
+ .setPackageName("package")
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
+ .build()
+ )
+ .build()
+ )
+ .addSafetySourcesGroup(
+ SafetySourcesGroup.Builder()
+ .setId("static")
+ .setTitleResId(R.string.reference)
+ .addSafetySource(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_STATIC)
+ .setId("static_barebone")
+ .setTitleResId(R.string.reference)
+ .setSummaryResId(R.string.reference)
+ .setIntentAction("intent")
+ .setProfile(SafetySource.PROFILE_PRIMARY)
+ .build()
+ )
+ .addSafetySource(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_STATIC)
+ .setId("static_all_optional")
+ .setTitleResId(R.string.reference)
+ .setTitleForWorkResId(R.string.reference)
+ .setSummaryResId(R.string.reference)
+ .setIntentAction("intent")
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setSearchTermsResId(R.string.reference)
+ .build()
+ )
+ .build()
+ )
+ .addSafetySourcesGroup(
+ SafetySourcesGroup.Builder()
+ .setId("issue_only")
+ .addSafetySource(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY)
+ .setId("issue_only_barebone")
+ .setPackageName("package")
+ .setProfile(SafetySource.PROFILE_PRIMARY)
+ .build()
+ )
+ .addSafetySource(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY)
+ .setId("issue_only_all_optional")
+ .setPackageName("package")
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setMaxSeverityLevel(300)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
+ .build()
+ )
+ .build()
+ )
+ .addSafetySourcesGroup(
+ SafetySourcesGroup.Builder()
+ .setId("mixed")
+ .setTitleResId(R.string.reference)
+ .addSafetySource(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId("mixed_dynamic_barebone")
+ .setPackageName("package")
+ .setTitleResId(R.string.reference)
+ .setSummaryResId(R.string.reference)
+ .setIntentAction("intent")
+ .setProfile(SafetySource.PROFILE_PRIMARY)
+ .build()
+ )
+ .addSafetySource(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY)
+ .setId("mixed_issue_only_barebone")
+ .setPackageName("package")
+ .setProfile(SafetySource.PROFILE_PRIMARY)
+ .build()
+ )
+ .addSafetySource(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_STATIC)
+ .setId("mixed_static_barebone")
+ .setTitleResId(R.string.reference)
+ .setSummaryResId(R.string.reference)
+ .setIntentAction("intent")
+ .setProfile(SafetySource.PROFILE_PRIMARY)
+ .build()
+ )
+ .build()
+ )
+ .build()
+ assertThat(actual).isEqualTo(expected)
+ }
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetyCenterConfigTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetyCenterConfigTest.kt
new file mode 100644
index 000000000..7ae036ccb
--- /dev/null
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetyCenterConfigTest.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.safetycenter.cts.config
+
+import android.os.Build.VERSION_CODES.TIRAMISU
+import android.safetycenter.config.SafetyCenterConfig
+import android.safetycenter.cts.testing.EqualsHashCodeToStringTester
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.ext.truth.os.ParcelableSubject.assertThat
+import androidx.test.filters.SdkSuppress
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** CTS tests for [SafetyCenterConfig]. */
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
+class SafetyCenterConfigTest {
+
+ @Test
+ fun getSafetySources_returnsSafetySources() {
+ assertThat(BASE.safetySourcesGroups)
+ .containsExactly(SafetySourcesGroupTest.RIGID, SafetySourcesGroupTest.HIDDEN)
+ .inOrder()
+ }
+
+ @Test
+ fun describeContents_returns0() {
+ assertThat(BASE.describeContents()).isEqualTo(0)
+ }
+
+ @Test
+ fun parcelRoundTrip_recreatesEqual() {
+ assertThat(BASE).recreatesEqual(SafetyCenterConfig.CREATOR)
+ }
+
+ @Test
+ fun equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
+ EqualsHashCodeToStringTester()
+ .addEqualityGroup(
+ BASE,
+ SafetyCenterConfig.Builder()
+ .addSafetySourcesGroup(SafetySourcesGroupTest.RIGID)
+ .addSafetySourcesGroup(SafetySourcesGroupTest.HIDDEN)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetyCenterConfig.Builder()
+ .addSafetySourcesGroup(SafetySourcesGroupTest.HIDDEN)
+ .addSafetySourcesGroup(SafetySourcesGroupTest.RIGID)
+ .build()
+ )
+ .test()
+ }
+
+ companion object {
+ private val BASE =
+ SafetyCenterConfig.Builder()
+ .addSafetySourcesGroup(SafetySourcesGroupTest.RIGID)
+ .addSafetySourcesGroup(SafetySourcesGroupTest.HIDDEN)
+ .build()
+ }
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourceTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourceTest.kt
new file mode 100644
index 000000000..616405dd1
--- /dev/null
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourceTest.kt
@@ -0,0 +1,557 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.safetycenter.cts.config
+
+import android.content.res.Resources
+import android.os.Build.VERSION_CODES.TIRAMISU
+import android.safetycenter.config.SafetySource
+import android.safetycenter.cts.testing.EqualsHashCodeToStringTester
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.ext.truth.os.ParcelableSubject.assertThat
+import androidx.test.filters.SdkSuppress
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.assertThrows
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** CTS tests for [SafetySource]. */
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
+class SafetySourceTest {
+
+ @Test
+ fun getType_returnsType() {
+ assertThat(DYNAMIC_BAREBONE.type).isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ assertThat(DYNAMIC_ALL_OPTIONAL.type).isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ assertThat(DYNAMIC_HIDDEN.type).isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ assertThat(DYNAMIC_DISABLED.type).isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ assertThat(STATIC_BAREBONE.type).isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_STATIC)
+ assertThat(STATIC_ALL_OPTIONAL.type).isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_STATIC)
+ assertThat(ISSUE_ONLY_BAREBONE.type).isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY)
+ assertThat(ISSUE_ONLY_ALL_OPTIONAL.type).isEqualTo(
+ SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY)
+ }
+
+ @Test
+ fun getId_returnsId() {
+ assertThat(DYNAMIC_BAREBONE.id).isEqualTo(DYNAMIC_BAREBONE_ID)
+ assertThat(DYNAMIC_ALL_OPTIONAL.id).isEqualTo(DYNAMIC_ALL_OPTIONAL_ID)
+ assertThat(DYNAMIC_HIDDEN.id).isEqualTo(DYNAMIC_HIDDEN_ID)
+ assertThat(DYNAMIC_DISABLED.id).isEqualTo(DYNAMIC_DISABLED_ID)
+ assertThat(STATIC_BAREBONE.id).isEqualTo(STATIC_BAREBONE_ID)
+ assertThat(STATIC_ALL_OPTIONAL.id).isEqualTo(STATIC_ALL_OPTIONAL_ID)
+ assertThat(ISSUE_ONLY_BAREBONE.id).isEqualTo(ISSUE_ONLY_BAREBONE_ID)
+ assertThat(ISSUE_ONLY_ALL_OPTIONAL.id).isEqualTo(ISSUE_ONLY_ALL_OPTIONAL_ID)
+ }
+
+ @Test
+ fun getPackageName_returnsPackageNameOrThrows() {
+ assertThat(DYNAMIC_BAREBONE.packageName).isEqualTo(PACKAGE_NAME)
+ assertThat(DYNAMIC_ALL_OPTIONAL.packageName).isEqualTo(PACKAGE_NAME)
+ assertThat(DYNAMIC_HIDDEN.packageName).isEqualTo(PACKAGE_NAME)
+ assertThat(DYNAMIC_DISABLED.packageName).isEqualTo(PACKAGE_NAME)
+ assertThrows(UnsupportedOperationException::class.java) { STATIC_BAREBONE.packageName }
+ assertThrows(UnsupportedOperationException::class.java) { STATIC_ALL_OPTIONAL.packageName }
+ assertThat(ISSUE_ONLY_BAREBONE.packageName).isEqualTo(PACKAGE_NAME)
+ assertThat(ISSUE_ONLY_ALL_OPTIONAL.packageName).isEqualTo(PACKAGE_NAME)
+ }
+
+ @Test
+ fun getTitleResId_returnsTitleResIdOrThrows() {
+ assertThat(DYNAMIC_BAREBONE.titleResId).isEqualTo(REFERENCE_RES_ID)
+ assertThat(DYNAMIC_ALL_OPTIONAL.titleResId).isEqualTo(REFERENCE_RES_ID)
+ assertThat(DYNAMIC_DISABLED.titleResId).isEqualTo(REFERENCE_RES_ID)
+ assertThat(DYNAMIC_HIDDEN.titleResId).isEqualTo(Resources.ID_NULL)
+ assertThat(STATIC_BAREBONE.titleResId).isEqualTo(REFERENCE_RES_ID)
+ assertThat(STATIC_ALL_OPTIONAL.titleResId).isEqualTo(REFERENCE_RES_ID)
+ assertThrows(UnsupportedOperationException::class.java) { ISSUE_ONLY_BAREBONE.titleResId }
+ assertThrows(
+ UnsupportedOperationException::class.java) { ISSUE_ONLY_ALL_OPTIONAL.titleResId }
+ }
+
+ @Test
+ fun getTitleForWorkResId_returnsTitleForWorkResIdOrThrows() {
+ assertThrows(
+ UnsupportedOperationException::class.java) { DYNAMIC_BAREBONE.titleForWorkResId }
+ assertThat(DYNAMIC_ALL_OPTIONAL.titleForWorkResId).isEqualTo(REFERENCE_RES_ID)
+ assertThrows(
+ UnsupportedOperationException::class.java) { DYNAMIC_DISABLED.titleForWorkResId }
+ assertThat(DYNAMIC_HIDDEN.titleForWorkResId).isEqualTo(Resources.ID_NULL)
+ assertThrows(
+ UnsupportedOperationException::class.java) { STATIC_BAREBONE.titleForWorkResId }
+ assertThat(STATIC_ALL_OPTIONAL.titleForWorkResId).isEqualTo(REFERENCE_RES_ID)
+ assertThrows(UnsupportedOperationException::class.java) {
+ ISSUE_ONLY_BAREBONE.titleForWorkResId
+ }
+ assertThrows(UnsupportedOperationException::class.java) {
+ ISSUE_ONLY_ALL_OPTIONAL.titleForWorkResId
+ }
+ }
+
+ @Test
+ fun getSummaryResId_returnsSummaryResIdOrThrows() {
+ assertThat(DYNAMIC_BAREBONE.summaryResId).isEqualTo(REFERENCE_RES_ID)
+ assertThat(DYNAMIC_ALL_OPTIONAL.summaryResId).isEqualTo(REFERENCE_RES_ID)
+ assertThat(DYNAMIC_DISABLED.summaryResId).isEqualTo(REFERENCE_RES_ID)
+ assertThat(DYNAMIC_HIDDEN.summaryResId).isEqualTo(Resources.ID_NULL)
+ assertThat(STATIC_BAREBONE.summaryResId).isEqualTo(REFERENCE_RES_ID)
+ assertThat(STATIC_ALL_OPTIONAL.summaryResId).isEqualTo(REFERENCE_RES_ID)
+ assertThrows(UnsupportedOperationException::class.java) { ISSUE_ONLY_BAREBONE.summaryResId }
+ assertThrows(
+ UnsupportedOperationException::class.java) { ISSUE_ONLY_ALL_OPTIONAL.summaryResId }
+ }
+
+ @Test
+ fun getIntentAction_returnsIntentActionOrThrows() {
+ assertThat(DYNAMIC_BAREBONE.intentAction).isEqualTo(INTENT_ACTION)
+ assertThat(DYNAMIC_ALL_OPTIONAL.intentAction).isEqualTo(INTENT_ACTION)
+ assertThat(DYNAMIC_DISABLED.intentAction).isNull()
+ assertThat(DYNAMIC_HIDDEN.intentAction).isNull()
+ assertThat(STATIC_BAREBONE.intentAction).isEqualTo(INTENT_ACTION)
+ assertThat(STATIC_ALL_OPTIONAL.intentAction).isEqualTo(INTENT_ACTION)
+ assertThrows(UnsupportedOperationException::class.java) { ISSUE_ONLY_BAREBONE.intentAction }
+ assertThrows(
+ UnsupportedOperationException::class.java) { ISSUE_ONLY_ALL_OPTIONAL.intentAction }
+ }
+
+ @Test
+ fun getProfile_returnsProfile() {
+ assertThat(DYNAMIC_BAREBONE.profile).isEqualTo(SafetySource.PROFILE_PRIMARY)
+ assertThat(DYNAMIC_ALL_OPTIONAL.profile).isEqualTo(SafetySource.PROFILE_ALL)
+ assertThat(DYNAMIC_DISABLED.profile).isEqualTo(SafetySource.PROFILE_PRIMARY)
+ assertThat(DYNAMIC_HIDDEN.profile).isEqualTo(SafetySource.PROFILE_ALL)
+ assertThat(STATIC_BAREBONE.profile).isEqualTo(SafetySource.PROFILE_PRIMARY)
+ assertThat(STATIC_ALL_OPTIONAL.profile).isEqualTo(SafetySource.PROFILE_ALL)
+ assertThat(ISSUE_ONLY_BAREBONE.profile).isEqualTo(SafetySource.PROFILE_PRIMARY)
+ assertThat(ISSUE_ONLY_ALL_OPTIONAL.profile).isEqualTo(SafetySource.PROFILE_ALL)
+ }
+
+ @Test
+ fun getInitialDisplayState_returnsInitialDisplayStateOrThrows() {
+ assertThat(DYNAMIC_BAREBONE.initialDisplayState)
+ .isEqualTo(SafetySource.INITIAL_DISPLAY_STATE_ENABLED)
+ assertThat(DYNAMIC_ALL_OPTIONAL.initialDisplayState)
+ .isEqualTo(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
+ assertThat(DYNAMIC_DISABLED.initialDisplayState)
+ .isEqualTo(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
+ assertThat(DYNAMIC_HIDDEN.initialDisplayState)
+ .isEqualTo(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
+ assertThrows(
+ UnsupportedOperationException::class.java) { STATIC_BAREBONE.initialDisplayState }
+ assertThrows(UnsupportedOperationException::class.java) {
+ STATIC_ALL_OPTIONAL.initialDisplayState
+ }
+ assertThrows(UnsupportedOperationException::class.java) {
+ ISSUE_ONLY_BAREBONE.initialDisplayState
+ }
+ assertThrows(UnsupportedOperationException::class.java) {
+ ISSUE_ONLY_ALL_OPTIONAL.initialDisplayState
+ }
+ }
+
+ @Test
+ fun getMaxSeverityLevel_returnsMaxSeverityLevelOrThrows() {
+ assertThat(DYNAMIC_BAREBONE.maxSeverityLevel).isEqualTo(Integer.MAX_VALUE)
+ assertThat(DYNAMIC_ALL_OPTIONAL.maxSeverityLevel).isEqualTo(MAX_SEVERITY_LEVEL)
+ assertThat(DYNAMIC_DISABLED.maxSeverityLevel).isEqualTo(Integer.MAX_VALUE)
+ assertThat(DYNAMIC_HIDDEN.maxSeverityLevel).isEqualTo(Integer.MAX_VALUE)
+ assertThrows(UnsupportedOperationException::class.java) { STATIC_BAREBONE.maxSeverityLevel }
+ assertThrows(
+ UnsupportedOperationException::class.java) { STATIC_ALL_OPTIONAL.maxSeverityLevel }
+ assertThat(ISSUE_ONLY_BAREBONE.maxSeverityLevel).isEqualTo(Integer.MAX_VALUE)
+ assertThat(ISSUE_ONLY_ALL_OPTIONAL.maxSeverityLevel).isEqualTo(MAX_SEVERITY_LEVEL)
+ }
+
+ @Test
+ fun getSearchTermsResId_returnsSearchTermsResIdOrThrows() {
+ assertThat(DYNAMIC_BAREBONE.searchTermsResId).isEqualTo(Resources.ID_NULL)
+ assertThat(DYNAMIC_ALL_OPTIONAL.searchTermsResId).isEqualTo(REFERENCE_RES_ID)
+ assertThat(DYNAMIC_DISABLED.searchTermsResId).isEqualTo(Resources.ID_NULL)
+ assertThat(DYNAMIC_HIDDEN.searchTermsResId).isEqualTo(Resources.ID_NULL)
+ assertThat(STATIC_BAREBONE.searchTermsResId).isEqualTo(Resources.ID_NULL)
+ assertThat(STATIC_ALL_OPTIONAL.searchTermsResId).isEqualTo(REFERENCE_RES_ID)
+ assertThrows(
+ UnsupportedOperationException::class.java) { ISSUE_ONLY_BAREBONE.searchTermsResId }
+ assertThrows(UnsupportedOperationException::class.java) {
+ ISSUE_ONLY_ALL_OPTIONAL.searchTermsResId
+ }
+ }
+
+ @Test
+ fun isLoggingAllowed_returnsLoggingAllowedOrThrows() {
+ assertThat(DYNAMIC_BAREBONE.isLoggingAllowed).isEqualTo(true)
+ assertThat(DYNAMIC_ALL_OPTIONAL.isLoggingAllowed).isEqualTo(false)
+ assertThat(DYNAMIC_DISABLED.isLoggingAllowed).isEqualTo(true)
+ assertThat(DYNAMIC_HIDDEN.isLoggingAllowed).isEqualTo(true)
+ assertThrows(UnsupportedOperationException::class.java) { STATIC_BAREBONE.isLoggingAllowed }
+ assertThrows(
+ UnsupportedOperationException::class.java) { STATIC_ALL_OPTIONAL.isLoggingAllowed }
+ assertThat(ISSUE_ONLY_BAREBONE.isLoggingAllowed).isEqualTo(true)
+ assertThat(ISSUE_ONLY_ALL_OPTIONAL.isLoggingAllowed).isEqualTo(false)
+ }
+
+ @Test
+ fun isRefreshOnPageOpenAllowed_returnsRefreshOnPageOpenAllowedOrThrows() {
+ assertThat(DYNAMIC_BAREBONE.isRefreshOnPageOpenAllowed).isEqualTo(false)
+ assertThat(DYNAMIC_ALL_OPTIONAL.isRefreshOnPageOpenAllowed).isEqualTo(true)
+ assertThat(DYNAMIC_DISABLED.isRefreshOnPageOpenAllowed).isEqualTo(false)
+ assertThat(DYNAMIC_HIDDEN.isRefreshOnPageOpenAllowed).isEqualTo(false)
+ assertThrows(UnsupportedOperationException::class.java) {
+ STATIC_BAREBONE.isRefreshOnPageOpenAllowed
+ }
+ assertThrows(UnsupportedOperationException::class.java) {
+ STATIC_ALL_OPTIONAL.isRefreshOnPageOpenAllowed
+ }
+ assertThat(ISSUE_ONLY_BAREBONE.isRefreshOnPageOpenAllowed).isEqualTo(false)
+ assertThat(ISSUE_ONLY_ALL_OPTIONAL.isRefreshOnPageOpenAllowed).isEqualTo(true)
+ }
+
+ @Test
+ fun describeContents_returns0() {
+ assertThat(DYNAMIC_BAREBONE.describeContents()).isEqualTo(0)
+ assertThat(DYNAMIC_ALL_OPTIONAL.describeContents()).isEqualTo(0)
+ assertThat(DYNAMIC_HIDDEN.describeContents()).isEqualTo(0)
+ assertThat(DYNAMIC_DISABLED.describeContents()).isEqualTo(0)
+ assertThat(STATIC_BAREBONE.describeContents()).isEqualTo(0)
+ assertThat(STATIC_ALL_OPTIONAL.describeContents()).isEqualTo(0)
+ assertThat(ISSUE_ONLY_BAREBONE.describeContents()).isEqualTo(0)
+ assertThat(ISSUE_ONLY_ALL_OPTIONAL.describeContents()).isEqualTo(0)
+ }
+
+ @Test
+ fun parcelRoundTrip_recreatesEqual() {
+ assertThat(DYNAMIC_BAREBONE).recreatesEqual(SafetySource.CREATOR)
+ assertThat(DYNAMIC_ALL_OPTIONAL).recreatesEqual(SafetySource.CREATOR)
+ assertThat(DYNAMIC_HIDDEN).recreatesEqual(SafetySource.CREATOR)
+ assertThat(DYNAMIC_DISABLED).recreatesEqual(SafetySource.CREATOR)
+ assertThat(STATIC_BAREBONE).recreatesEqual(SafetySource.CREATOR)
+ assertThat(STATIC_ALL_OPTIONAL).recreatesEqual(SafetySource.CREATOR)
+ assertThat(ISSUE_ONLY_BAREBONE).recreatesEqual(SafetySource.CREATOR)
+ assertThat(ISSUE_ONLY_ALL_OPTIONAL).recreatesEqual(SafetySource.CREATOR)
+ }
+
+ @Test
+ fun equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
+ EqualsHashCodeToStringTester()
+ .addEqualityGroup(DYNAMIC_BAREBONE)
+ .addEqualityGroup(
+ DYNAMIC_ALL_OPTIONAL,
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId(DYNAMIC_ALL_OPTIONAL_ID)
+ .setPackageName(PACKAGE_NAME)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setTitleForWorkResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setIntentAction(INTENT_ACTION)
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
+ .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
+ .setSearchTermsResId(REFERENCE_RES_ID)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
+ .build()
+ )
+ .addEqualityGroup(DYNAMIC_HIDDEN)
+ .addEqualityGroup(DYNAMIC_DISABLED)
+ .addEqualityGroup(STATIC_BAREBONE)
+ .addEqualityGroup(STATIC_ALL_OPTIONAL)
+ .addEqualityGroup(ISSUE_ONLY_BAREBONE)
+ .addEqualityGroup(ISSUE_ONLY_ALL_OPTIONAL)
+ .addEqualityGroup(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId("other")
+ .setPackageName(PACKAGE_NAME)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setTitleForWorkResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setIntentAction(INTENT_ACTION)
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
+ .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
+ .setSearchTermsResId(REFERENCE_RES_ID)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId(DYNAMIC_ALL_OPTIONAL_ID)
+ .setPackageName("other")
+ .setTitleResId(REFERENCE_RES_ID)
+ .setTitleForWorkResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setIntentAction(INTENT_ACTION)
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
+ .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
+ .setSearchTermsResId(REFERENCE_RES_ID)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId(DYNAMIC_ALL_OPTIONAL_ID)
+ .setPackageName(PACKAGE_NAME)
+ .setTitleResId(-1)
+ .setTitleForWorkResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setIntentAction(INTENT_ACTION)
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
+ .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
+ .setSearchTermsResId(REFERENCE_RES_ID)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId(DYNAMIC_ALL_OPTIONAL_ID)
+ .setPackageName(PACKAGE_NAME)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setTitleForWorkResId(-1)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setIntentAction(INTENT_ACTION)
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
+ .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
+ .setSearchTermsResId(REFERENCE_RES_ID)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId(DYNAMIC_ALL_OPTIONAL_ID)
+ .setPackageName(PACKAGE_NAME)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setTitleForWorkResId(REFERENCE_RES_ID)
+ .setSummaryResId(-1)
+ .setIntentAction(INTENT_ACTION)
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
+ .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
+ .setSearchTermsResId(REFERENCE_RES_ID)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId(DYNAMIC_ALL_OPTIONAL_ID)
+ .setPackageName(PACKAGE_NAME)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setTitleForWorkResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setIntentAction("other")
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
+ .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
+ .setSearchTermsResId(REFERENCE_RES_ID)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId(DYNAMIC_HIDDEN_ID)
+ .setPackageName(PACKAGE_NAME)
+ .setProfile(SafetySource.PROFILE_PRIMARY)
+ .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId(DYNAMIC_ALL_OPTIONAL_ID)
+ .setPackageName(PACKAGE_NAME)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setTitleForWorkResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setIntentAction(INTENT_ACTION)
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_ENABLED)
+ .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
+ .setSearchTermsResId(REFERENCE_RES_ID)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId(DYNAMIC_ALL_OPTIONAL_ID)
+ .setPackageName(PACKAGE_NAME)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setTitleForWorkResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setIntentAction(INTENT_ACTION)
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
+ .setMaxSeverityLevel(-1)
+ .setSearchTermsResId(REFERENCE_RES_ID)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId(DYNAMIC_ALL_OPTIONAL_ID)
+ .setPackageName(PACKAGE_NAME)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setTitleForWorkResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setIntentAction(INTENT_ACTION)
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
+ .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
+ .setSearchTermsResId(-1)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId(DYNAMIC_ALL_OPTIONAL_ID)
+ .setPackageName(PACKAGE_NAME)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setTitleForWorkResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setIntentAction(INTENT_ACTION)
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
+ .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
+ .setSearchTermsResId(REFERENCE_RES_ID)
+ .setLoggingAllowed(true)
+ .setRefreshOnPageOpenAllowed(true)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId(DYNAMIC_ALL_OPTIONAL_ID)
+ .setPackageName(PACKAGE_NAME)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setTitleForWorkResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setIntentAction(INTENT_ACTION)
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
+ .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
+ .setSearchTermsResId(REFERENCE_RES_ID)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(false)
+ .build()
+ )
+ .test()
+ }
+
+ companion object {
+ private const val PACKAGE_NAME = "package"
+ private const val REFERENCE_RES_ID = 9999
+ private const val INTENT_ACTION = "intent"
+ private const val MAX_SEVERITY_LEVEL = 300
+
+ private const val DYNAMIC_BAREBONE_ID = "dynamic_barebone"
+ private const val DYNAMIC_ALL_OPTIONAL_ID = "dynamic_all_optional"
+ private const val DYNAMIC_DISABLED_ID = "dynamic_disabled"
+ private const val DYNAMIC_HIDDEN_ID = "dynamic_hidden"
+ private const val STATIC_BAREBONE_ID = "static_barebone"
+ private const val STATIC_ALL_OPTIONAL_ID = "static_all_optional"
+ private const val ISSUE_ONLY_BAREBONE_ID = "issue_only_barebone"
+ private const val ISSUE_ONLY_ALL_OPTIONAL_ID = "issue_only_all_optional"
+
+ internal val DYNAMIC_BAREBONE =
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId(DYNAMIC_BAREBONE_ID)
+ .setPackageName(PACKAGE_NAME)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setIntentAction(INTENT_ACTION)
+ .setProfile(SafetySource.PROFILE_PRIMARY)
+ .build()
+
+ private val DYNAMIC_ALL_OPTIONAL =
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId(DYNAMIC_ALL_OPTIONAL_ID)
+ .setPackageName(PACKAGE_NAME)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setTitleForWorkResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setIntentAction(INTENT_ACTION)
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
+ .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
+ .setSearchTermsResId(REFERENCE_RES_ID)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
+ .build()
+
+ private val DYNAMIC_DISABLED =
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId(DYNAMIC_DISABLED_ID)
+ .setPackageName(PACKAGE_NAME)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setProfile(SafetySource.PROFILE_PRIMARY)
+ .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
+ .build()
+
+ private val DYNAMIC_HIDDEN =
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId(DYNAMIC_HIDDEN_ID)
+ .setPackageName(PACKAGE_NAME)
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
+ .build()
+
+ internal val STATIC_BAREBONE =
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_STATIC)
+ .setId(STATIC_BAREBONE_ID)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setIntentAction(INTENT_ACTION)
+ .setProfile(SafetySource.PROFILE_PRIMARY)
+ .build()
+
+ private val STATIC_ALL_OPTIONAL =
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_STATIC)
+ .setId(STATIC_ALL_OPTIONAL_ID)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setTitleForWorkResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setIntentAction(INTENT_ACTION)
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setSearchTermsResId(REFERENCE_RES_ID)
+ .build()
+
+ internal val ISSUE_ONLY_BAREBONE =
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY)
+ .setId(ISSUE_ONLY_BAREBONE_ID)
+ .setPackageName(PACKAGE_NAME)
+ .setProfile(SafetySource.PROFILE_PRIMARY)
+ .build()
+
+ private val ISSUE_ONLY_ALL_OPTIONAL =
+ SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY)
+ .setId(ISSUE_ONLY_ALL_OPTIONAL_ID)
+ .setPackageName(PACKAGE_NAME)
+ .setProfile(SafetySource.PROFILE_ALL)
+ .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
+ .build()
+ }
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourcesGroupTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourcesGroupTest.kt
new file mode 100644
index 000000000..b04f9e4ce
--- /dev/null
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourcesGroupTest.kt
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.safetycenter.cts.config
+
+import android.content.res.Resources
+import android.os.Build.VERSION_CODES.TIRAMISU
+import android.safetycenter.config.SafetySourcesGroup
+import android.safetycenter.cts.testing.EqualsHashCodeToStringTester
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.ext.truth.os.ParcelableSubject.assertThat
+import androidx.test.filters.SdkSuppress
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** CTS tests for [SafetySourcesGroup]. */
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
+class SafetySourcesGroupTest {
+
+ @Test
+ fun getType_returnsType() {
+ assertThat(COLLAPSIBLE_WITH_SUMMARY.type)
+ .isEqualTo(SafetySourcesGroup.SAFETY_SOURCES_GROUP_TYPE_COLLAPSIBLE)
+ assertThat(COLLAPSIBLE_WITH_ICON.type)
+ .isEqualTo(SafetySourcesGroup.SAFETY_SOURCES_GROUP_TYPE_COLLAPSIBLE)
+ assertThat(COLLAPSIBLE_WITH_BOTH.type)
+ .isEqualTo(SafetySourcesGroup.SAFETY_SOURCES_GROUP_TYPE_COLLAPSIBLE)
+ assertThat(RIGID.type).isEqualTo(SafetySourcesGroup.SAFETY_SOURCES_GROUP_TYPE_RIGID)
+ assertThat(HIDDEN.type).isEqualTo(SafetySourcesGroup.SAFETY_SOURCES_GROUP_TYPE_HIDDEN)
+ }
+
+ @Test
+ fun getId_returnsId() {
+ assertThat(COLLAPSIBLE_WITH_SUMMARY.id).isEqualTo(COLLAPSIBLE_WITH_SUMMARY_ID)
+ assertThat(COLLAPSIBLE_WITH_ICON.id).isEqualTo(COLLAPSIBLE_WITH_ICON_ID)
+ assertThat(COLLAPSIBLE_WITH_BOTH.id).isEqualTo(COLLAPSIBLE_WITH_BOTH_ID)
+ assertThat(RIGID.id).isEqualTo(RIGID_ID)
+ assertThat(HIDDEN.id).isEqualTo(HIDDEN_ID)
+ }
+
+ @Test
+ fun getTitleResId_returnsTitleResId() {
+ assertThat(COLLAPSIBLE_WITH_SUMMARY.titleResId).isEqualTo(REFERENCE_RES_ID)
+ assertThat(COLLAPSIBLE_WITH_ICON.titleResId).isEqualTo(REFERENCE_RES_ID)
+ assertThat(COLLAPSIBLE_WITH_BOTH.titleResId).isEqualTo(REFERENCE_RES_ID)
+ assertThat(RIGID.titleResId).isEqualTo(REFERENCE_RES_ID)
+ // This is not an enforced invariant, titleResId should just be ignored for hidden groups
+ assertThat(HIDDEN.titleResId).isEqualTo(Resources.ID_NULL)
+ }
+
+ @Test
+ fun getSummaryResId_returnsSummaryResId() {
+ assertThat(COLLAPSIBLE_WITH_SUMMARY.summaryResId).isEqualTo(REFERENCE_RES_ID)
+ assertThat(COLLAPSIBLE_WITH_ICON.summaryResId).isEqualTo(Resources.ID_NULL)
+ assertThat(COLLAPSIBLE_WITH_BOTH.summaryResId).isEqualTo(REFERENCE_RES_ID)
+ assertThat(RIGID.summaryResId).isEqualTo(Resources.ID_NULL)
+ // This is not an enforced invariant, summaryResId should just be ignored for hidden groups
+ assertThat(HIDDEN.summaryResId).isEqualTo(Resources.ID_NULL)
+ }
+
+ @Test
+ fun getStatelessIconType_returnsStatelessIconType() {
+ assertThat(COLLAPSIBLE_WITH_SUMMARY.statelessIconType)
+ .isEqualTo(SafetySourcesGroup.STATELESS_ICON_TYPE_NONE)
+ assertThat(COLLAPSIBLE_WITH_ICON.statelessIconType)
+ .isEqualTo(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
+ assertThat(COLLAPSIBLE_WITH_BOTH.statelessIconType)
+ .isEqualTo(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
+ assertThat(RIGID.statelessIconType).isEqualTo(SafetySourcesGroup.STATELESS_ICON_TYPE_NONE)
+ // This is not an enforced invariant
+ // statelessIconType should just be ignored for hidden groups
+ assertThat(HIDDEN.statelessIconType).isEqualTo(SafetySourcesGroup.STATELESS_ICON_TYPE_NONE)
+ }
+
+ @Test
+ fun getSafetySources_returnsSafetySources() {
+ assertThat(COLLAPSIBLE_WITH_SUMMARY.safetySources)
+ .containsExactly(SafetySourceTest.DYNAMIC_BAREBONE)
+ assertThat(COLLAPSIBLE_WITH_ICON.safetySources)
+ .containsExactly(SafetySourceTest.STATIC_BAREBONE)
+ assertThat(COLLAPSIBLE_WITH_BOTH.safetySources)
+ .containsExactly(
+ SafetySourceTest.DYNAMIC_BAREBONE,
+ SafetySourceTest.STATIC_BAREBONE,
+ SafetySourceTest.ISSUE_ONLY_BAREBONE
+ )
+ .inOrder()
+ assertThat(RIGID.safetySources).containsExactly(SafetySourceTest.STATIC_BAREBONE)
+ assertThat(HIDDEN.safetySources).containsExactly(SafetySourceTest.ISSUE_ONLY_BAREBONE)
+ }
+
+ @Test
+ fun describeContents_returns0() {
+ assertThat(COLLAPSIBLE_WITH_SUMMARY.describeContents()).isEqualTo(0)
+ assertThat(COLLAPSIBLE_WITH_ICON.describeContents()).isEqualTo(0)
+ assertThat(COLLAPSIBLE_WITH_BOTH.describeContents()).isEqualTo(0)
+ assertThat(RIGID.describeContents()).isEqualTo(0)
+ assertThat(HIDDEN.describeContents()).isEqualTo(0)
+ }
+
+ @Test
+ fun parcelRoundTrip_recreatesEqual() {
+ assertThat(COLLAPSIBLE_WITH_SUMMARY).recreatesEqual(SafetySourcesGroup.CREATOR)
+ assertThat(COLLAPSIBLE_WITH_ICON).recreatesEqual(SafetySourcesGroup.CREATOR)
+ assertThat(COLLAPSIBLE_WITH_BOTH).recreatesEqual(SafetySourcesGroup.CREATOR)
+ assertThat(RIGID).recreatesEqual(SafetySourcesGroup.CREATOR)
+ assertThat(HIDDEN).recreatesEqual(SafetySourcesGroup.CREATOR)
+ }
+
+ @Test
+ fun equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
+ EqualsHashCodeToStringTester()
+ .addEqualityGroup(COLLAPSIBLE_WITH_SUMMARY)
+ .addEqualityGroup(COLLAPSIBLE_WITH_ICON)
+ .addEqualityGroup(
+ COLLAPSIBLE_WITH_BOTH,
+ SafetySourcesGroup.Builder()
+ .setId(COLLAPSIBLE_WITH_BOTH_ID)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
+ .addSafetySource(SafetySourceTest.DYNAMIC_BAREBONE)
+ .addSafetySource(SafetySourceTest.STATIC_BAREBONE)
+ .addSafetySource(SafetySourceTest.ISSUE_ONLY_BAREBONE)
+ .build()
+ )
+ .addEqualityGroup(RIGID)
+ .addEqualityGroup(HIDDEN)
+ .addEqualityGroup(
+ SafetySourcesGroup.Builder()
+ .setId("other")
+ .setTitleResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
+ .addSafetySource(SafetySourceTest.DYNAMIC_BAREBONE)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySourcesGroup.Builder()
+ .setId(COLLAPSIBLE_WITH_BOTH_ID)
+ .setTitleResId(-1)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
+ .addSafetySource(SafetySourceTest.DYNAMIC_BAREBONE)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySourcesGroup.Builder()
+ .setId(COLLAPSIBLE_WITH_BOTH_ID)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setSummaryResId(-1)
+ .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
+ .addSafetySource(SafetySourceTest.DYNAMIC_BAREBONE)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySourcesGroup.Builder()
+ .setId(COLLAPSIBLE_WITH_BOTH_ID)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_NONE)
+ .addSafetySource(SafetySourceTest.DYNAMIC_BAREBONE)
+ .build()
+ )
+ .addEqualityGroup(
+ SafetySourcesGroup.Builder()
+ .setId(COLLAPSIBLE_WITH_BOTH_ID)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
+ .addSafetySource(SafetySourceTest.STATIC_BAREBONE)
+ .build()
+ )
+ .test()
+ }
+
+ companion object {
+ private const val REFERENCE_RES_ID = 9999
+
+ private const val COLLAPSIBLE_WITH_SUMMARY_ID = "collapsible_with_summary"
+ private const val COLLAPSIBLE_WITH_ICON_ID = "collapsible_with_icon"
+ private const val COLLAPSIBLE_WITH_BOTH_ID = "collapsible_with_both"
+ private const val RIGID_ID = "rigid"
+ private const val HIDDEN_ID = "hidden"
+
+ private val COLLAPSIBLE_WITH_SUMMARY =
+ SafetySourcesGroup.Builder()
+ .setId(COLLAPSIBLE_WITH_SUMMARY_ID)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .addSafetySource(SafetySourceTest.DYNAMIC_BAREBONE)
+ .build()
+
+ private val COLLAPSIBLE_WITH_ICON =
+ SafetySourcesGroup.Builder()
+ .setId(COLLAPSIBLE_WITH_ICON_ID)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
+ .addSafetySource(SafetySourceTest.STATIC_BAREBONE)
+ .build()
+
+ private val COLLAPSIBLE_WITH_BOTH =
+ SafetySourcesGroup.Builder()
+ .setId(COLLAPSIBLE_WITH_BOTH_ID)
+ .setTitleResId(REFERENCE_RES_ID)
+ .setSummaryResId(REFERENCE_RES_ID)
+ .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
+ .addSafetySource(SafetySourceTest.DYNAMIC_BAREBONE)
+ .addSafetySource(SafetySourceTest.STATIC_BAREBONE)
+ .addSafetySource(SafetySourceTest.ISSUE_ONLY_BAREBONE)
+ .build()
+
+ internal val RIGID =
+ SafetySourcesGroup.Builder()
+ .setId(RIGID_ID)
+ .setTitleResId(REFERENCE_RES_ID)
+ .addSafetySource(SafetySourceTest.STATIC_BAREBONE)
+ .build()
+
+ internal val HIDDEN =
+ SafetySourcesGroup.Builder()
+ .setId(HIDDEN_ID)
+ .addSafetySource(SafetySourceTest.ISSUE_ONLY_BAREBONE)
+ .build()
+ }
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/XmlConfigTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/config/XmlConfigTest.kt
index 9b77e994e..b3f6bfb12 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/XmlConfigTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/config/XmlConfigTest.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.safetycenter.cts
+package android.safetycenter.cts.config
import android.os.Build.VERSION_CODES.TIRAMISU
import android.safetycenter.config.SafetyCenterConfig
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/testing/Coroutines.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/testing/Coroutines.kt
new file mode 100644
index 000000000..379b32b2f
--- /dev/null
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/testing/Coroutines.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.safetycenter.cts.testing
+
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withTimeout
+import java.time.Duration
+
+/** A class that facilitates interacting with coroutines. */
+object Coroutines {
+
+ /** Behaves in the same way as [runBlocking], but with a timeout. */
+ fun <T> runBlockingWithTimeout(timeout: Duration = TIMEOUT_LONG, block: suspend () -> T) =
+ runBlocking {
+ withTimeout(timeout.toMillis()) { block() }
+ }
+
+ /** A long timeout, to be used for actions that are expected to complete. */
+ val TIMEOUT_LONG: Duration = Duration.ofSeconds(5)
+
+ /** A short timeout, to be used for actions that are expected not to complete. */
+ val TIMEOUT_SHORT: Duration = Duration.ofSeconds(1)
+} \ No newline at end of file
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/testing/EqualsHashCodeToStringTester.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/testing/EqualsHashCodeToStringTester.kt
new file mode 100644
index 000000000..f44b8c372
--- /dev/null
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/testing/EqualsHashCodeToStringTester.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.safetycenter.cts.testing
+
+import com.google.common.base.Equivalence
+import com.google.common.testing.EqualsTester
+import com.google.common.testing.EquivalenceTester
+
+/**
+ * A class similar to [EqualsTester] that also checks that the [Object.hashCode] and
+ * [Object.toString] implementations are consistent with equality groups.
+ *
+ * Note: this class assumes that [Object.hashCode] does not create a collision for equality groups,
+ * however this can be disabled by setting [hashCodeCanCollide] to `true`.
+ */
+class EqualsHashCodeToStringTester(private val hashCodeCanCollide: Boolean = false) {
+ private val equalsTester = EqualsTester()
+ private val toStringTester = EquivalenceTester.of(TO_STRING_EQUIVALENCE)
+ private val hashCodeTester = EquivalenceTester.of(HASH_CODE_EQUIVALENCE)
+
+ fun addEqualityGroup(vararg groups: Any): EqualsHashCodeToStringTester {
+ equalsTester.addEqualityGroup(groups)
+ toStringTester.addEquivalenceGroup(groups)
+ if (!hashCodeCanCollide) {
+ hashCodeTester.addEquivalenceGroup(groups)
+ }
+ return this
+ }
+
+ fun test() {
+ equalsTester.testEquals()
+ toStringTester.test()
+ if (!hashCodeCanCollide) {
+ hashCodeTester.test()
+ }
+ }
+
+ companion object {
+
+ /**
+ * An [Equivalence] that considers two instances of a class equivalent iff [Object.toString]
+ * return the same value.
+ */
+ private val TO_STRING_EQUIVALENCE = object : Equivalence<Any>() {
+
+ override fun doEquivalent(a: Any, b: Any): Boolean {
+ return a.toString() == b.toString()
+ }
+
+ override fun doHash(o: Any): Int {
+ return o.toString().hashCode()
+ }
+ }
+
+ /**
+ * An [Equivalence] that considers two instances of a class equivalent iff [Object.hashCode]
+ * return the same value.
+ */
+ private val HASH_CODE_EQUIVALENCE = object : Equivalence<Any>() {
+
+ override fun doEquivalent(a: Any, b: Any): Boolean {
+ return a.hashCode() == b.hashCode()
+ }
+
+ override fun doHash(o: Any): Int {
+ return o.hashCode()
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/testing/FakeExecutor.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/testing/FakeExecutor.kt
new file mode 100644
index 000000000..7cd83f9ee
--- /dev/null
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/testing/FakeExecutor.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.safetycenter.cts.testing
+
+import android.safetycenter.cts.testing.Coroutines.TIMEOUT_LONG
+import android.safetycenter.cts.testing.Coroutines.runBlockingWithTimeout
+import kotlinx.coroutines.TimeoutCancellationException
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED
+import java.time.Duration
+import java.util.concurrent.Executor
+
+/**
+ * An [Executor] that can control when the supplied [Runnable] is actually executed.
+ *
+ * This is useful to test concurrency issues, as it allows sequencing the [Executor] in a
+ * deterministic order.
+ */
+class FakeExecutor : Executor {
+ private val tasks = Channel<Runnable>(UNLIMITED)
+
+ override fun execute(task: Runnable) {
+ runBlockingWithTimeout { tasks.send(task) }
+ }
+
+ /**
+ * Returns the next submitted task to this executor.
+ *
+ * If a task was already submitted, this call returns it immediately.
+ *
+ * If no task was submitted, this call returns the next task submitted within the given
+ * [timeout] and throws a [TimeoutCancellationException] exception otherwise.
+ *
+ * Note: the returned task is not run when returned. Use [Runnable.run] to actually run it.
+ */
+ fun getNextTask(timeout: Duration = TIMEOUT_LONG) =
+ runBlockingWithTimeout {
+ tasks.receive()
+ }
+} \ No newline at end of file
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/testing/Generic.java b/tests/cts/safetycenter/src/android/safetycenter/cts/testing/Generic.java
new file mode 100644
index 000000000..67733a70b
--- /dev/null
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/testing/Generic.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.safetycenter.cts.testing;
+
+/** A class that facilitates working with {@code null} values in Kotlin. */
+public final class Generic {
+
+ /**
+ * Returns a {@code T} as a {@code null} value.
+ *
+ * <p>This is used to trick Kotlin into allowing {@code null} values for {@code @NonNull}
+ * fields.
+ */
+ @SuppressWarnings("TypeParameterUnusedInFormals")
+ public static <T> T asNull() {
+ return null;
+ }
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/testing/SafetyCenterApisWithShellPermissions.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/testing/SafetyCenterApisWithShellPermissions.kt
new file mode 100644
index 000000000..dbbac5303
--- /dev/null
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/testing/SafetyCenterApisWithShellPermissions.kt
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.safetycenter.cts.testing
+
+import android.Manifest.permission.MANAGE_SAFETY_CENTER
+import android.Manifest.permission.READ_SAFETY_CENTER_STATUS
+import android.Manifest.permission.SEND_SAFETY_CENTER_UPDATE
+import android.safetycenter.SafetyCenterData
+import android.safetycenter.SafetyCenterManager
+import android.safetycenter.SafetyCenterManager.OnSafetyCenterDataChangedListener
+import android.safetycenter.SafetyEvent
+import android.safetycenter.SafetySourceData
+import android.safetycenter.SafetySourceErrorDetails
+import android.safetycenter.config.SafetyCenterConfig
+import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
+import java.util.concurrent.Executor
+
+/**
+ * Extension methods for [SafetyCenterManager] that delegate to the relevant implementation, but
+ * making each call with the appropriate permission.
+ */
+object SafetyCenterApisWithShellPermissions {
+
+ /**
+ * Calls [SafetyCenterManager.isSafetyCenterEnabled] adopting Shell's
+ * [READ_SAFETY_CENTER_STATUS] permission.
+ */
+ fun SafetyCenterManager.isSafetyCenterEnabledWithPermission(): Boolean =
+ callWithShellPermissionIdentity({ isSafetyCenterEnabled }, READ_SAFETY_CENTER_STATUS)
+
+ /**
+ * Calls [SafetyCenterManager.setSafetySourceData] adopting Shell's [SEND_SAFETY_CENTER_UPDATE]
+ * permission.
+ */
+ fun SafetyCenterManager.setSafetySourceDataWithPermission(
+ safetySourceId: String,
+ safetySourceData: SafetySourceData?,
+ safetyEvent: SafetyEvent
+ ) {
+ callWithShellPermissionIdentity(
+ { setSafetySourceData(safetySourceId, safetySourceData, safetyEvent) },
+ SEND_SAFETY_CENTER_UPDATE
+ )
+ }
+
+ /**
+ * Calls [SafetyCenterManager.getSafetySourceData] adopting Shell's [SEND_SAFETY_CENTER_UPDATE]
+ * permission.
+ */
+ fun SafetyCenterManager.getSafetySourceDataWithPermission(id: String): SafetySourceData? =
+ callWithShellPermissionIdentity({ getSafetySourceData(id) }, SEND_SAFETY_CENTER_UPDATE)
+
+ /**
+ * Calls [SafetyCenterManager.reportSafetySourceError] adopting Shell's
+ * [SEND_SAFETY_CENTER_UPDATE] permission.
+ */
+ fun SafetyCenterManager.reportSafetySourceErrorWithPermission(
+ safetySourceId: String,
+ safetySourceErrorDetails: SafetySourceErrorDetails
+ ) {
+ callWithShellPermissionIdentity(
+ { reportSafetySourceError(safetySourceId, safetySourceErrorDetails) },
+ SEND_SAFETY_CENTER_UPDATE
+ )
+ }
+
+ /**
+ * Calls [SafetyCenterManager.refreshSafetySources] adopting Shell's [MANAGE_SAFETY_CENTER]
+ * permission.
+ */
+ fun SafetyCenterManager.refreshSafetySourcesWithPermission(refreshReason: Int) {
+ callWithShellPermissionIdentity({ refreshSafetySources(refreshReason) },
+ MANAGE_SAFETY_CENTER)
+ }
+
+ /**
+ * Calls [SafetyCenterManager.getSafetyCenterConfig] adopting Shell's [MANAGE_SAFETY_CENTER]
+ * permission.
+ */
+ fun SafetyCenterManager.getSafetyCenterConfigWithPermission(): SafetyCenterConfig? =
+ callWithShellPermissionIdentity(::getSafetyCenterConfig, MANAGE_SAFETY_CENTER)
+
+ /**
+ * Calls [SafetyCenterManager.getSafetyCenterData] adopting Shell's [MANAGE_SAFETY_CENTER]
+ * permission.
+ */
+ fun SafetyCenterManager.getSafetyCenterDataWithPermission(): SafetyCenterData =
+ callWithShellPermissionIdentity(::getSafetyCenterData, MANAGE_SAFETY_CENTER)
+
+ /**
+ * Calls [SafetyCenterManager.addOnSafetyCenterDataChangedListener] adopting Shell's
+ * [MANAGE_SAFETY_CENTER] permission.
+ */
+ fun SafetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(
+ executor: Executor,
+ listener: OnSafetyCenterDataChangedListener
+ ) {
+ callWithShellPermissionIdentity(
+ { addOnSafetyCenterDataChangedListener(executor, listener) },
+ MANAGE_SAFETY_CENTER
+ )
+ }
+
+ /**
+ * Calls [SafetyCenterManager.removeOnSafetyCenterDataChangedListener] adopting Shell's
+ * [MANAGE_SAFETY_CENTER] permission.
+ */
+ fun SafetyCenterManager.removeOnSafetyCenterDataChangedListenerWithPermission(
+ listener: OnSafetyCenterDataChangedListener
+ ) {
+ callWithShellPermissionIdentity(
+ { removeOnSafetyCenterDataChangedListener(listener) },
+ MANAGE_SAFETY_CENTER
+ )
+ }
+
+ /**
+ * Calls [SafetyCenterManager.dismissSafetyCenterIssue] adopting Shell's [MANAGE_SAFETY_CENTER]
+ * permission.
+ */
+ fun SafetyCenterManager.dismissSafetyCenterIssueWithPermission(safetyCenterIssueId: String) {
+ callWithShellPermissionIdentity(
+ { dismissSafetyCenterIssue(safetyCenterIssueId) },
+ MANAGE_SAFETY_CENTER
+ )
+ }
+
+ /**
+ * Calls [SafetyCenterManager.executeSafetyCenterIssueAction] adopting Shell's
+ * [MANAGE_SAFETY_CENTER] permission.
+ */
+ fun SafetyCenterManager.executeSafetyCenterIssueActionWithPermission(
+ safetyCenterIssueId: String,
+ safetyCenterIssueActionId: String
+ ) {
+ callWithShellPermissionIdentity(
+ { executeSafetyCenterIssueAction(safetyCenterIssueId, safetyCenterIssueActionId) },
+ MANAGE_SAFETY_CENTER
+ )
+ }
+
+ /**
+ * Calls [SafetyCenterManager.clearAllSafetySourceDataForTests] adopting Shell's
+ * [MANAGE_SAFETY_CENTER] permission.
+ */
+ fun SafetyCenterManager.clearAllSafetySourceDataForTestsWithPermission() =
+ callWithShellPermissionIdentity(
+ { clearAllSafetySourceDataForTests() }, MANAGE_SAFETY_CENTER)
+
+ /**
+ * Calls [SafetyCenterManager.setSafetyCenterConfigForTests] adopting Shell's
+ * [MANAGE_SAFETY_CENTER] permission.
+ */
+ fun SafetyCenterManager.setSafetyCenterConfigForTestsWithPermission(
+ safetyCenterConfig: SafetyCenterConfig
+ ) {
+ callWithShellPermissionIdentity(
+ { setSafetyCenterConfigForTests(safetyCenterConfig) },
+ MANAGE_SAFETY_CENTER
+ )
+ }
+
+ /**
+ * Calls [SafetyCenterManager.clearSafetyCenterConfigForTests] adopting Shell's
+ * [MANAGE_SAFETY_CENTER] permission.
+ */
+ fun SafetyCenterManager.clearSafetyCenterConfigForTestsWithPermission() {
+ callWithShellPermissionIdentity(
+ { clearSafetyCenterConfigForTests() }, MANAGE_SAFETY_CENTER)
+ }
+} \ No newline at end of file
diff --git a/tests/cts/safetycenter/src/android/safetycenter/testing/SafetyCenterFlags.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/testing/SafetyCenterFlags.kt
index 8ae335c7c..70c1b304d 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/testing/SafetyCenterFlags.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/testing/SafetyCenterFlags.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.safetycenter.testing
+package android.safetycenter.cts.testing
import android.Manifest.permission.WRITE_DEVICE_CONFIG
import android.content.Context
@@ -52,4 +52,4 @@ object SafetyCenterFlags {
WRITE_DEVICE_CONFIG
)
}
-} \ No newline at end of file
+}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/testing/SafetySourceBroadcastReceiver.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/testing/SafetySourceBroadcastReceiver.kt
index 8097d9dbb..43fe195b0 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/testing/SafetySourceBroadcastReceiver.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/testing/SafetySourceBroadcastReceiver.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.safetycenter.testing
+package android.safetycenter.cts.testing
import android.content.BroadcastReceiver
import android.content.Context
@@ -27,10 +27,12 @@ import android.safetycenter.SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_REQ
import android.safetycenter.SafetyEvent
import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_REFRESH_REQUESTED
import android.safetycenter.SafetySourceData
-import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.withTimeout
+import android.safetycenter.cts.testing.Coroutines.TIMEOUT_LONG
+import android.safetycenter.cts.testing.Coroutines.runBlockingWithTimeout
+import android.safetycenter.cts.testing.SafetyCenterApisWithShellPermissions.setSafetySourceDataWithPermission
import java.time.Duration
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED
/** Broadcast receiver to be used for testing broadcasts sent to safety source apps. */
class SafetySourceBroadcastReceiver : BroadcastReceiver() {
@@ -60,7 +62,7 @@ class SafetySourceBroadcastReceiver : BroadcastReceiver() {
)
}
- runBlocking { updateChannel.send(Unit) }
+ runBlockingWithTimeout { updateChannel.send(Unit) }
}
companion object {
@@ -70,7 +72,7 @@ class SafetySourceBroadcastReceiver : BroadcastReceiver() {
.build()
@Volatile
- private var updateChannel = Channel<Unit>()
+ private var updateChannel = Channel<Unit>(UNLIMITED)
@Volatile
var safetySourceId: String? = null
@@ -89,8 +91,8 @@ class SafetySourceBroadcastReceiver : BroadcastReceiver() {
updateChannel = Channel()
}
- fun waitTillOnReceiveComplete(duration: Duration) {
- runBlocking { withTimeout(duration.toMillis()) { updateChannel.receive() } }
+ fun waitTillOnReceiveComplete(timeout: Duration = TIMEOUT_LONG) {
+ runBlockingWithTimeout(timeout) { updateChannel.receive() }
}
}
}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/testing/AnyTester.kt b/tests/cts/safetycenter/src/android/safetycenter/testing/AnyTester.kt
deleted file mode 100644
index 50c37a39a..000000000
--- a/tests/cts/safetycenter/src/android/safetycenter/testing/AnyTester.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.testing
-
-import com.google.common.truth.Truth.assertThat
-
-/** Collection of functions to test generic objects */
-object AnyTester {
- /**
- * Asserts that two generic objects are equal and that the values returned by the [hashCode] and
- * [toString] methods for the two generic objects are also equal.
- */
- fun assertThatRepresentationsAreEqual(a: Any, b: Any) {
- assertThat(a.hashCode()).isEqualTo(b.hashCode())
- assertThat(a).isEqualTo(b)
- assertThat(a.toString()).isEqualTo(b.toString())
- }
-
- /**
- * Asserts that two generic objects are not equal and that the values returned by the [hashCode]
- * and [toString] methods for the two generic objects are also not equal.
- */
- fun assertThatRepresentationsAreNotEqual(a: Any, b: Any) {
- assertThat(a.hashCode()).isNotEqualTo(b.hashCode())
- assertThat(a).isNotEqualTo(b)
- assertThat(a.toString()).isNotEqualTo(b.toString())
- }
-} \ No newline at end of file
diff --git a/tests/cts/safetycenter/src/android/safetycenter/testing/ParcelableTester.kt b/tests/cts/safetycenter/src/android/safetycenter/testing/ParcelableTester.kt
deleted file mode 100644
index 0ba599993..000000000
--- a/tests/cts/safetycenter/src/android/safetycenter/testing/ParcelableTester.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package android.safetycenter.testing
-
-import android.os.Parcel
-import android.os.Parcelable
-import com.google.common.truth.Truth.assertThat
-
-/** Collection of functions to test [Parcelable] objects */
-object ParcelableTester {
- /**
- * Asserts that writing a [Parcelable] object to a [Parcel] and creating an object from that
- * [Parcel] returns an object that is equal to the original [Parcelable] object.
- */
- fun <T : Parcelable> assertThatRoundTripReturnsOriginal(
- parcelable: T,
- creator: Parcelable.Creator<T>
- ) {
- val parcel: Parcel = Parcel.obtain()
- parcelable.writeToParcel(parcel, 0)
- parcel.setDataPosition(0)
- val parcelableFromParcel: T = creator.createFromParcel(parcel)
- parcel.recycle()
-
- assertThat(parcelableFromParcel).isEqualTo(parcelable)
- }
-} \ No newline at end of file
diff --git a/tests/cts/safetycenter/src/android/safetycenter/testing/SafetyCenterApisWithShellPermissions.kt b/tests/cts/safetycenter/src/android/safetycenter/testing/SafetyCenterApisWithShellPermissions.kt
deleted file mode 100644
index b874b8219..000000000
--- a/tests/cts/safetycenter/src/android/safetycenter/testing/SafetyCenterApisWithShellPermissions.kt
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.testing
-
-import android.Manifest.permission.MANAGE_SAFETY_CENTER
-import android.Manifest.permission.READ_SAFETY_CENTER_STATUS
-import android.Manifest.permission.SEND_SAFETY_CENTER_UPDATE
-import android.safetycenter.SafetyCenterManager
-import android.safetycenter.SafetyCenterManager.OnSafetyCenterDataChangedListener
-import android.safetycenter.SafetyEvent
-import android.safetycenter.SafetySourceData
-import android.safetycenter.SafetySourceErrorDetails
-import android.safetycenter.config.SafetyCenterConfig
-import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
-import java.util.concurrent.Executor
-
-/**
- * Calls [SafetyCenterManager.isSafetyCenterEnabled] adopting Shell's [READ_SAFETY_CENTER_STATUS]
- * permission.
- */
-fun SafetyCenterManager.isSafetyCenterEnabledWithPermission() =
- callWithShellPermissionIdentity({ isSafetyCenterEnabled }, READ_SAFETY_CENTER_STATUS)
-
-/**
- * Calls [SafetyCenterManager.setSafetySourceData] adopting Shell's [SEND_SAFETY_CENTER_UPDATE]
- * permission.
- */
-fun SafetyCenterManager.setSafetySourceDataWithPermission(
- safetySourceId: String,
- safetySourceData: SafetySourceData?,
- safetyEvent: SafetyEvent
-) =
- callWithShellPermissionIdentity(
- { setSafetySourceData(safetySourceId, safetySourceData, safetyEvent) },
- SEND_SAFETY_CENTER_UPDATE
- )
-
-/**
- * Calls [SafetyCenterManager.getSafetySourceData] adopting Shell's [SEND_SAFETY_CENTER_UPDATE]
- * permission.
- */
-fun SafetyCenterManager.getSafetySourceDataWithPermission(id: String) =
- callWithShellPermissionIdentity({ getSafetySourceData(id) }, SEND_SAFETY_CENTER_UPDATE)
-
-/**
- * Calls [SafetyCenterManager.reportSafetySourceError] adopting Shell's [SEND_SAFETY_CENTER_UPDATE]
- * permission.
- */
-fun SafetyCenterManager.reportSafetySourceErrorWithPermission(
- safetySourceId: String,
- safetySourceErrorDetails: SafetySourceErrorDetails
-) =
- callWithShellPermissionIdentity(
- { reportSafetySourceError(safetySourceId, safetySourceErrorDetails) },
- SEND_SAFETY_CENTER_UPDATE
- )
-
-/**
- * Calls [SafetyCenterManager.refreshSafetySources] adopting Shell's [MANAGE_SAFETY_CENTER]
- * permission.
- */
-fun SafetyCenterManager.refreshSafetySourcesWithPermission(refreshReason: Int) =
- callWithShellPermissionIdentity({ refreshSafetySources(refreshReason) }, MANAGE_SAFETY_CENTER)
-
-/**
- * Calls [SafetyCenterManager.getSafetyCenterData] adopting Shell's [MANAGE_SAFETY_CENTER]
- * permission.
- */
-fun SafetyCenterManager.getSafetyCenterDataWithPermission() =
- callWithShellPermissionIdentity(::getSafetyCenterData, MANAGE_SAFETY_CENTER)
-
-/**
- * Calls [SafetyCenterManager.addOnSafetyCenterDataChangedListener] adopting Shell's
- * [MANAGE_SAFETY_CENTER] permission.
- */
-fun SafetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(
- executor: Executor,
- listener: OnSafetyCenterDataChangedListener
-) =
- callWithShellPermissionIdentity(
- { addOnSafetyCenterDataChangedListener(executor, listener) },
- MANAGE_SAFETY_CENTER
- )
-
-/**
- * Calls [SafetyCenterManager.removeOnSafetyCenterDataChangedListener] adopting Shell's
- * [MANAGE_SAFETY_CENTER] permission.
- */
-fun SafetyCenterManager.removeOnSafetyCenterDataChangedListenerWithPermission(
- listener: OnSafetyCenterDataChangedListener
-) =
- callWithShellPermissionIdentity(
- { removeOnSafetyCenterDataChangedListener(listener) },
- MANAGE_SAFETY_CENTER
- )
-
-/**
- * Calls [SafetyCenterManager.dismissSafetyCenterIssue] adopting Shell's [MANAGE_SAFETY_CENTER]
- * permission.
- */
-fun SafetyCenterManager.dismissSafetyCenterIssueWithPermission(safetyCenterIssueId: String) =
- callWithShellPermissionIdentity({ dismissSafetyCenterIssue(safetyCenterIssueId) },
- MANAGE_SAFETY_CENTER)
-
-/**
- * Calls [SafetyCenterManager.executeSafetyCenterIssueAction] adopting Shell's
- * [MANAGE_SAFETY_CENTER] permission.
- */
-fun SafetyCenterManager.executeSafetyCenterIssueActionWithPermission(
- safetyCenterIssueId: String,
- safetyCenterIssueActionId: String
-) =
- callWithShellPermissionIdentity(
- { executeSafetyCenterIssueAction(safetyCenterIssueId, safetyCenterIssueActionId) },
- MANAGE_SAFETY_CENTER
- )
-
-/**
- * Calls [SafetyCenterManager.clearAllSafetySourceData] adopting Shell's [MANAGE_SAFETY_CENTER]
- * permission.
- */
-fun SafetyCenterManager.clearAllSafetySourceDataWithPermission() =
- callWithShellPermissionIdentity({ clearAllSafetySourceData() }, MANAGE_SAFETY_CENTER)
-
-/**
- * Calls [SafetyCenterManager.setSafetyCenterConfigOverride] adopting Shell's [MANAGE_SAFETY_CENTER]
- * permission.
- */
-fun SafetyCenterManager.setSafetyCenterConfigOverrideWithPermission(
- safetyCenterConfig: SafetyCenterConfig
-) =
- callWithShellPermissionIdentity(
- { setSafetyCenterConfigOverride(safetyCenterConfig) },
- MANAGE_SAFETY_CENTER
- )
-
-/**
- * Calls [SafetyCenterManager.clearSafetyCenterConfigOverride] adopting Shell's
- * [MANAGE_SAFETY_CENTER] permission.
- */
-fun SafetyCenterManager.clearSafetyCenterConfigOverrideWithPermission() =
- callWithShellPermissionIdentity({ clearSafetyCenterConfigOverride() }, MANAGE_SAFETY_CENTER)